[解題報告]hdoj1269(強連通tarjan)
阿新 • • 發佈:2019-01-08
大概題意,多組輸入n,m(表示n個房間,m條路徑)接著輸入m個u,v,表示u->v,判斷是否任意兩個房間相互連通,是輸出Yes,否則No
/* 2014-10-15 23:57 62ms/1500k tarjan演算法:基於對圖深度優先搜尋,每個強連通分量為搜尋樹中的一顆子樹,把當前搜尋樹中未處理的結點加入堆疊,通過<回溯>判斷。 此題我出現的問題。。:居然先用了鄰接矩陣和棧!MLE。。然後就是一些小問題,j,v等等寫錯,粗心。 */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; int n,m; int index,scc,top;//訪問序號,強連通分量個數,棧頂位置 struct Edge { int to; int next;// } edge[100003]; int head[10003];//起始房間所在邊序號 int stack[10003]; bool in[10003];//判斷是否在棧中 int DFN[10003],LOW[10003];//dfn時間戳,low存祖先序號 void tarjan(int i) { DFN[i]=LOW[i]=++index; stack[++top]=i; in[i]=true;// int j,v; for(j=head[i]; j!=-1; j=edge[j].next) { v=edge[j].to; if(!DFN[v])//指向結點沒有被訪問過 { tarjan(v); LOW[i]=min(LOW[i],LOW[v]);//兩節點可能不在同一強連通分量中 } else if(in[v])//訪問過 而且仍在棧中 LOW[i]=min(LOW[i],DFN[v]); } if(DFN[i]==LOW[i])//該結點是強連通分量的根 { //更新個數,並將找到的強連通分量結點退棧 scc++; do { j=stack[top--]; in[j]=false;// }while(j!=i); } } void solve() { index=0,scc=0,top=0; memset(DFN,0,sizeof(DFN)); memset(in,false,sizeof(in)); for(int i=1; i<=n; i++) { if(!DFN[i]) tarjan(i); } } int main() { while(~scanf("%d%d",&n,&m),n+m) { int a,b; int i; memset(head,-1,sizeof(head)); for(i=0; i<m; i++) { scanf("%d%d",&a,&b); edge[i].to=b; edge[i].next=head[a];// head[a]=i; } solve(); if(scc==1) printf("Yes\n"); else printf("No\n"); } return 0; }