题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23727
思路:首先是Tarjan找桥,对于桥,只能是双向边,而对于同一个连通分量而言,只要重新定向为同一个方向即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<queue> 7 #include<vector> 8 using namespace std; 9 #define MAXN 1111 10 typedef pair<int,int>PP; 11 12 int low[MAXN],dfn[MAXN]; 13 bool mark[MAXN]; 14 int _count,cnt; 15 vector<int>g[MAXN]; 16 vector<PP>bridge; 17 bool vis[MAXN][MAXN]; 18 int n,m; 19 20 void Tarjan(int u,int father) 21 { 22 int flag=0; 23 low[u]=dfn[u]=++cnt; 24 mark[u]=true; 25 for(int i=0;i<(int)g[u].size();i++){ 26 int v=g[u][i]; 27 if(v==father&&!flag){ flag=1;continue; } 28 if(dfn[v]==0){ 29 Tarjan(v,u); 30 low[u]=min(low[u],low[v]); 31 if(low[v]>dfn[u]){ 32 bridge.push_back(make_pair(u,v)); 33 bridge.push_back(make_pair(v,u)); 34 vis[u][v]=vis[v][u]=true; 35 }else { 36 bridge.push_back(make_pair(u,v)); 37 vis[u][v]=vis[v][u]=true; 38 } 39 }else if(mark[v]){ 40 low[u]=min(low[u],dfn[v]); 41 if(!vis[u][v]){ 42 bridge.push_back(make_pair(u,v)); 43 vis[u][v]=vis[v][u]=true; 44 } 45 } 46 } 47 } 48 49 int main() 50 { 51 int u,v,t=1; 52 while(~scanf("%d%d",&n,&m)){ 53 if(n==0&&m==0)break; 54 for(int i=0;i<=n+1;i++)g[i].clear(); 55 bridge.clear(); 56 while(m--){ 57 scanf("%d%d",&u,&v); 58 g[u].push_back(v); 59 g[v].push_back(u); 60 } 61 memset(mark,false,sizeof(mark)); 62 memset(dfn,0,sizeof(dfn)); 63 memset(vis,false,sizeof(vis)); 64 _count=cnt=0; 65 Tarjan(1,-1); 66 printf("%d\n\n",t++); 67 for(int i=0;i<(int)bridge.size();i++){ 68 printf("%d %d\n",bridge[i].first,bridge[i].second); 69 } 70 puts("#"); 71 } 72 return 0; 73 } 74 75 76 77 78 79 80 81 82 83