真神奇...一个多月前写的稍微修改了一下日期就成今天了
本文不适合用于学习!!!只是一份模板(还是很烂的模板
颓了近一个月猛然发现要比赛了,终于下定决心用写博客的方式来帮自己整理复习。当然我也只是个混了一个月的蒟蒻,学过的东西相当有限,只希望自己能坚持下去吧......
那么就从我上周学的tarjan开始!
//求一张n个点、m条边的图中的联通分量并打印结果
#include<cstdio>
#include<stack>
#include<algorithm>
using namespace std;
const int MAXN = 10005;
const int MAXM = 50005;
int n,m;
struct Edge{
int next,to;//next指的是下一条边
}edge[MAXM];
int head[MAXN],cnt;
void addedge(int from,int to){
edge[++cnt].next = head[from];
edge[cnt].to = to;
head[from] = cnt;
}
int dfn[MAXN],low[MAXN],tme,instack[MAXN];
stack<int> zhan;
void tarjan(int x){
dfn[x] = low[x] = ++tme;
instack[x] = 1;
zhan.push(x);
for(int i = head[x];i;i = edge[i].next){
int y = edge[i].to;
if(instack[y] == 0) {tarjan(y);low[x] = min(low[x],low[y]);}
else if(instack[y] == 1) low[x] = min(low[x],dfn[y]);//事实上这里也可以用low[y]但若是用tarjan求割点之类的东西则必须用dfn,所以就记dfn吧!
}
if(low[x] == dfn[x]){
while(!zhan.empty()){
int m = zhan.top();
printf("%d ",m);
zhan.pop();
if(m == x) break;
}
printf("\n");
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
}
for(int i = 1;i <= n;i++)
if(!dfn[i]) tarjan(i);//这是为了防止整个图不连通
return 0;
}