第一个模板有误!!!!
请见谅!!!
要怪就怪HDU吧,竟然让我过了
第二个模板是正确的。请翻到下面看更新
HDU 1269
评论区居然有人说用并查集过了,其实回想一下
求无向图的连通分量,就是并查集,求有向图的话,就要用到这个算法,或者Kosaraju。
再回想一下,Tarjan确实比较像并查集,我在第一次写的时候就有这种感觉
请看:
这是我在找强连通分量的数量,而在并查集里面,就是:
这样看来,其实,low的含义就是这个f[i],而由于有向图有其顺序的,所以用num[i]记录其访问的顺序。。。。。
无论是代码,还是算法,Tarjan都像极了并查集,不得不说,Trajan其实就是一个高级并查集算法
下面贴下我的模板,这个模板只是过了HDU 1269,看discuss数据比较水,不是太敢确定模板的正确性
说明:num记录访问的顺序,book记录是否访问过,low--按并查集的说法,就是更新它的爸爸,直到它的祖宗(想一下整个算法,确实如此)
有机会看一下这个吧,他写的蛮好的,我就是看了这个才看懂
https://blog.csdn.net/mengxiang000000/article/details/51672725
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
vector<int>u[];
bool book[];
int index;
int num[],low[];
void Tarjan_dfs(int t)
{
index++;book[t]=true;
low[t]=num[t]=index;
for(int i=;i<u[t].size();i++){
if(!book[u[t][i]]){
Tarjan_dfs(u[t][i]);
}
low[t]=min(low[t],low[u[t][i]]);
}
} int main()
{
int n,m;
while(cin>>n>>m&&n&&m){
int x,y;
index=;
memset(book,,sizeof(book));
for(int i=;i<m;i++){
cin>>x>>y;
u[x].push_back(y);
}
for(int i=;i<=n;i++){
if(!book[i]){Tarjan_dfs(i);}
}
int ans=;
for(int i=;i<=n;i++){
if(low[i]==num[i]){ans++;}
}
for(int i=;i<=n;i++){
printf("%d %d\n",num[i],low[i]);
}
cout<<ans<<endl;
}
return ;
}
——————————————————————————————————————————————————————————————————
实在抱歉,居然搞了一个错误的模板。
由于模板的错误,之前的理解也有些偏差,其实和并查集相似的不是low,而是color。
接下来是我的板子,这是POJ2553的代码,只有solve函数与此题有关。
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
int n,m;
int book[50008];
int low[50008],num[50008],cnt=1,index;
int color[50008];
bool flag[50008];
vector<int>u[50008];
stack<int>st;
int sig=0;
void Tarjan(int t)
{
num[t]=low[t]=++index;
st.push(t);
book[t]=true;
int siz=u[t].size();
for(int i=0;i<siz;i++){
if(!num[u[t][i]]){
Tarjan(u[t][i]);
low[t]=min(low[t],low[u[t][i]]);
}
else if(book[u[t][i]]){low[t]=min(low[t],low[u[t][i]]);}
} if(num[t]==low[t]){
sig++;
while(1){ cnt=st.top();
st.pop();
color[cnt]=sig;
book[cnt]=0;
if(cnt==t){break;}
}
}
} bool init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
u[i].clear();
}
while(!st.empty()){
st.pop();
}
memset(book,0,sizeof(book));
memset(low,0,sizeof(low));
memset(flag,0,sizeof(flag));
memset(color,0,sizeof(color));
memset(num,0,sizeof(num));
index=0;
if(n==0){return false;}
scanf("%d",&m);
int x,y;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
u[x].push_back(y);
}
return true;
} void solve()
{
int siz;
int tle=0;
for(int i=1;i<=n;i++){
siz=u[i].size();
for(int j=0;j<siz;j++){
if(color[u[i][j]]!=color[i]){flag[color[i]]=true;}
}
} for(int i=1;i<=n;i++){
if(!flag[color[i]]){
tle++?printf(" %d",i):printf("%d",i);
}
}
printf("\n");
} int main()
{
while(init()){
for(int i=1;i<=n;i++){
if(!num[i]){Tarjan(i);cnt++;}
}
solve();
}
}
Tarjan 模板,高级并查集的更多相关文章
-
洛谷P3367 【模板】并查集
P3367 [模板]并查集 293通过 551提交 题目提供者HansBug 标签 难度普及- 提交 讨论 题解 最新讨论 不知道哪错了 为啥通不过最后三个节点 题解 不懂为什么MLE 最后一个数 ...
-
洛谷 P3367 【模板】并查集
P3367 [模板]并查集 题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入输出格式 输入格式: 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数 ...
-
并查集 P3367 【模板】并查集
P3367 [模板]并查集 #include<iostream> #include<algorithm> #include<cstdio> #include< ...
-
《程序员代码面试指南》第三章 二叉树问题 Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题
题目待续.... Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题 java代码
-
POJ 2762 tarjan缩点+并查集+度数
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15494 ...
-
并查集模板题----P3367 【模板】并查集
题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入格式 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1时,将Xi与Yi ...
-
【并查集模板】并查集模板 luogu-3367
题目描述 简单的并查集模板 输入描述 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1时,将Xi与Yi所在的集合合并 当Zi=2时,输出 ...
-
Luogu P3367 【模板】并查集
题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入输出格式 输入格式: 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1 ...
-
题解 P3367 【【模板】并查集】
#include<iostream> #include<cstdio> using namespace std; int n,m,x,y,z; ]; //f[i]表示i的祖先 ...
随机推荐
-
通过 listboxitem 查找属于listbox第几条数据
public override System.Windows.Style SelectStyle(object item, System.Windows.DependencyObject contai ...
-
bestcoder杯回顾
题目列表:hdu5214~5223 5214: 当时第一反应是由递推公式推出通项公式,事实证明这就是作!大!死! 因为通项公式是这样的:L[n]=a^(n-1)*(b+L[1])-b 于是就需要快速幂 ...
-
java 整体字体样式设置
两种方式: 1.UIManager.put("Button.font", new Font("MS UI Gothic", Font.PLAIN, 24)) ...
-
<;jsp:forward>;、requestDispatcher和sendRedirect()的区别
1.会话信息保存在服务器内存上,可以断续访问,和cookie相比,其保存在服务器上. 2.男人就像蓝牙:只有在你接近时,他才会找上你.当你离开后,他便又去找其他的"设备"了.女人就 ...
-
ie6789和其他浏览器之间的鼠标左、中、右键的event.button不一致的办法
左键 中键 右键 Ie6 1 4 2 Ie7 1 4 2 Ie8 1 4 2 Ie9和其它 0 1 2 以下代码将IE6/7/8的值转换成符合W3C标准的方法: var ie678 = !-[1, ...
-
python 进制 转换
测试用的python源码 ''''' Created on 2014年8月21日 @author: lenovo ''' import binascii import struct def examp ...
-
python基础2 day3
一.上节回顾 1,while else2,格式化输出name = input('>>>')s1 = '我叫%s,今年%d岁'%(name,18)dic1name = input('& ...
-
vue子组件向父组件传值
vue2.0中通过$emit事件在子组件中自定义事件,通过操作子组件中的事件,向父组件传递参数: 首先写一个叫做parentComp.vue的父组件: <template> <div ...
-
unity8个入门代码
01,基本碰撞检测代码 function OnCollisionEnter(theCollision:Collision){ if(theCollision.gameObject.name==&quo ...
-
kettle学习笔记(一)——入门与安装
一.概述 1.kettle是什么 Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,绿色无需安装,数据抽取高效稳定.中文名称叫水壶,该项目的主程序 ...