uva 796 Critical Links【求割橋】
阿新 • • 發佈:2018-12-07
求割橋模板題;
割橋定義:一個強連通分量去掉這條邊變成多個強連通分量
判斷:橋無向邊(u,v),當且僅當(u,v)為樹枝邊,且滿足dfn[u]<low[v];
這道題注意是讓按升序輸出,並且要按照格式輸入輸出
#include<cstring> #include<string> #include<cstdio> #include<stdlib.h> #include<iostream> #include<algorithm> #include<math.h> #include<map> #include<vector> #include<stack> #define inf 0x3f3f3f3f #include<queue> #include<set> using namespace std; typedef long long ll; const int N=1e5+5;//資料開的儘量大 const int M=1e6+5; struct NOde { int v,ne; }edge[M];//存邊 int head[N]; int low[N],dfn[N],vis[N]; int e,cut,top,n; struct Brige { int u,v; }bri[M];//存割橋 bool cmp(Brige a,Brige b)//題目說按升序輸出 { if(a.u==b.u) return a.v<b.v; return a.u<b.u; } void add(int a,int b) { edge[e].v=b; edge[e].ne=head[a]; head[a]=e++; } void init() { memset(head,-1,sizeof(head)); e=0;cut=0; } void tarjan(int now,int pre) { low[now]=dfn[now]=++top; for(int i=head[now];i!=-1;i=edge[i].ne) { int v=edge[i].v; if(dfn[v]==0) { tarjan(v,now); low[now]=min(low[now],low[v]); if(dfn[now]<low[v])//判斷是否為割橋 { bri[cut].u=min(now,v);//這裡注意!!!!要讓小的試起點 bri[cut++].v=max(v,now); } } else if(dfn[v]<dfn[now]&&v!=pre)//如果v已被訪問,說明(u,v)室反向邊,用反向邊更新low low[now]=min(low[now],dfn[v]); } } void solve() { top=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(int i=1;i<=n;i++)//圖可能不是強連通,要遍歷每個點 { if(dfn[i]==0) tarjan(i,-1); } } int main() { while(~scanf("%d",&n)) { int a,sum,b; init(); for(int i=0;i<n;i++) { scanf("%d (%d)",&a,&sum); a++; for(int j=0;j<sum;j++) { scanf("%d",&b); b++; add(a,b); } } solve(); printf("%d critical links\n",cut); sort(bri,bri+cut,cmp); for(int i=0;i<cut;i++) printf("%d - %d\n",bri[i].u-1,bri[i].v-1); printf("\n"); } return 0; }