割边模板
判断方面,没有了割点的root的特判,并且==号去掉
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1e3+10; 7 8 int dfn[maxn],low[maxn],head[maxn],vis[maxn]; 9 bool judge[maxn]; 10 int k,n,m,num,root; 11 struct Edge{ 12 int to,next; 13 }G[400010]; 14 struct node 15 { 16 int u,v; 17 }sto[maxn]; int cot; 18 //这个大小应该跟边数同步,但这里跟点的个数同步也能过; 19 //大概是因为割边的数量不多吧 20 void build(int u,int v){ 21 G[num].to=v;G[num].next=head[u];head[u]=num++; 22 } 23 24 void Tarjan(int u,int fa){ 25 int son=0; 26 vis[u]=1; //判断是否访问过,当访问完后定为2,不再访问; 27 k++; 28 dfn[u]=k; //当前顶点的时间戳 29 low[u]=k; //当前顶点能够访问到的最小时间戳 一开始是自己 30 for(int i=head[u];i!=-1;i=G[i].next){ 31 int v=G[i].to; 32 //如果定点i曾经被访问过,并且这个定点不是当前u的父亲,就说明 33 //此时的i为U的祖先,所以更新u的权值 34 if(vis[v]==1&&v!=fa) 35 low[u]=min(low[u],dfn[v]); 36 if(vis[v]==0){ 37 Tarjan(v,u); 38 son++; 39 //更新当前顶点u能访问到的最早顶点的时间戳; 40 low[u]=min(low[u],low[v]); 41 //如果是根节点,就必须要有两个儿子才会使割点; 42 //不是根节点,就要满足dfn[u]<=low[v] 43 if(dfn[u]<low[v]){ 44 cot++; 45 if(u<v) sto[cot].u=u-1,sto[cot].v=v-1; 46 else sto[cot].u=v-1,sto[cot].v=u-1; 47 } 48 } 49 } 50 vis[u]=2; 51 } 52 bool cmp(node a,node b) 53 { 54 if(a.u==b.u) return a.v<b.v; 55 else return a.u<b.u; 56 } 57 int main(){ 58 while(scanf("%d%d",&n,&m)!=EOF){ 59 memset(head,-1,sizeof(head)); 60 memset(dfn,0,sizeof(dfn)); 61 memset(low,0,sizeof(low)); 62 memset(vis,0,sizeof(vis)); 63 memset(judge,0,sizeof(judge)); 64 num=0;cot=0; 65 int u,v; 66 for(int i=1;i<=m;i++){ 67 scanf("%d%d",&u,&v); 68 u++;v++; 69 build(u,v); 70 build(v,u); 71 } 72 root=1; 73 Tarjan(root,-1); 74 printf("%d\n",cot); 75 if(!cot) printf("\n"); 76 else{ 77 sort(sto+1,sto+1+cot,cmp); 78 for(int i=1;i<=cot;i++) 79 printf("%d %d\n",sto[i].u,sto[i].v); 80 printf("\n"); 81 } 82 } 83 return 0; 84 }