loj 1026( tarjan + 输出割边 )
题目链接:http://lightoj.com/volume_showproblem.php?problem=1026
思路:Tarjan 算法简单应用。割边的特点:low[v]>dfn[u](v是u的子节点)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 22222 8 9 struct Edge{ 10 int v,next; 11 }edge[MAXN*22]; 12 13 int n,NE; 14 int head[MAXN]; 15 16 void Insert(int u,int v) 17 { 18 edge[NE].v=v; 19 edge[NE].next=head[u]; 20 head[u]=NE++; 21 } 22 23 int cnt,bcc_count; 24 int low[MAXN],dfn[MAXN]; 25 bool mark[MAXN]; 26 vector<pair<int,int> >bridge; 27 28 void Tarjan(int u,int father) 29 { 30 int flag=0; 31 low[u]=dfn[u]=++cnt; 32 mark[u]=true; 33 for(int i=head[u];i!=-1;i=edge[i].next){ 34 int v=edge[i].v; 35 if(v==father&&!flag){ flag=1;continue; } 36 if(dfn[v]==0){ 37 Tarjan(v,u); 38 low[u]=min(low[u],low[v]); 39 if(low[v]>dfn[u]){ 40 bridge.push_back(make_pair(min(u,v),max(u,v))); 41 } 42 }else if(mark[v]){ 43 low[u]=min(low[u],dfn[v]); 44 } 45 } 46 } 47 48 int cmp(const pair<int,int>p,const pair<int,int>q) 49 { 50 if(p.first!=q.first)return p.first<q.first; 51 return p.second<q.second; 52 } 53 54 int main() 55 { 56 int _case,u,v,x,t=1; 57 scanf("%d",&_case); 58 while(_case--){ 59 scanf("%d",&n); 60 NE=0; 61 memset(head,-1,sizeof(head)); 62 for(int i=0;i<n;i++){ 63 scanf("%d (%d)",&u,&x); 64 while(x--){ 65 scanf("%d",&v); 66 Insert(u,v); 67 } 68 } 69 bridge.clear(); 70 cnt=bcc_count=0; 71 memset(dfn,0,sizeof(dfn)); 72 memset(mark,false,sizeof(mark)); 73 for(int i=0;i<n;i++)if(dfn[i]==0)Tarjan(i,-1); 74 printf("Case %d:\n",t++); 75 printf("%d critical links\n",(int)bridge.size()); 76 sort(bridge.begin(),bridge.end(),cmp); 77 for(int i=0;i<(int)bridge.size();i++){ 78 printf("%d - %d\n",bridge[i].first,bridge[i].second); 79 } 80 } 81 return 0; 82 }