题意:有n个人,它们之间有m个关系,关系是相互的,也就是边是无向边,现在问这个无向图有多少个桥,然后把这个桥的两个端点输出出来。
想法:tarjan边双连通,col为总的桥数因为col=0也是一个块,输出桥的端点名字即可。
#include<iostream> #include<cstring> #include<cstdio> #include<stack> #include<map> using namespace std; const int N=10000+50; const int M=200000+50; int n,m; struct node { int v,next; }e[M]; struct nodee { int u,v; char name1[20],name2[20]; }rsp[M/2]; map<string,int>mp; int head[N],cnt; int low[N],dfn[N],col,index; stack<int>s; void Init() { while(!s.empty()) s.pop(); memset(head,-1,sizeof(head)); cnt=col=index=0; memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); } void add(int a,int b) { e[cnt].v=b; e[cnt].next=head[a]; head[a]=cnt++; } int Min(int a,int b) { if(a<b) return a; return b; } void tarjan(int u,int f) { low[u]=dfn[u]=++index; s.push(u); for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(!dfn[v]) { tarjan(v,u); low[u]=Min(low[u],low[v]); if(low[v]>dfn[u]) ++col; } else if(v!=f) { low[u]=Min(low[u],dfn[v]); } } } int main() { int t; scanf("%d",&t); while(t--) { int num=0; mp.clear(); Init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%s%s",rsp[i].name1,rsp[i].name2); if(!mp[rsp[i].name1]) mp[rsp[i].name1]=++num; if(!mp[rsp[i].name2]) mp[rsp[i].name2]=++num; int a=mp[rsp[i].name1],b=mp[rsp[i].name2]; add(a,b); add(b,a); rsp[i].u=a; rsp[i].v=b; } tarjan(1,-1); int mark=1; for(int i=1;i<=n;i++) { if(!dfn[i]) { mark=0; break; } } if(!mark) { printf("0\n"); continue; } printf("%d\n",col); for(int i=1;i<=m;i++) { int u=rsp[i].u; int v=rsp[i].v; if(low[v]>dfn[u]||low[u]>dfn[v]) { printf("%s %s\n",rsp[i].name1,rsp[i].name2); } } } return 0; }