poj2762 Going from u to v or from v to u? (tarjan求有向图强联通分量/缩点)
本来准备回去了,想想看了一晚上,还是过一个模板题吧==
这题比赛时候其实就有思路了,就是将强连通分量缩点成一个DAG,然后判断是否成一条链,会个tarjan就是裸题啊==
不说了图论实在太弱,tarjan竟然刚学,放个模板明天继续学图论=
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<vector> 5 #include<stack> 6 using namespace std; 7 #define maxn 100005 8 vector<int>G[maxn],newnode[maxn]; 9 stack<int>s; 10 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; 11 //点对应时间戳,连通分量最小时间戳,连通分量编号,时间戳,连通分量数 12 int n,m,ans,into[maxn]; 13 void tarjan(int u){ 14 pre[u]=lowlink[u]=++dfs_clock; 15 s.push(u); 16 for (int i=0;i<G[u].size();i++){ 17 int v=G[u][i]; 18 if (!pre[v]){ 19 tarjan(v); 20 lowlink[u]=min(lowlink[u],lowlink[v]); 21 } 22 else if (!sccno[v]) 23 lowlink[u]=min(lowlink[u],pre[v]); 24 } 25 if (lowlink[u]==pre[u]){ 26 scc_cnt++; 27 while (1){ 28 int x=s.top(); s.pop(); 29 sccno[x]=scc_cnt; 30 if (x==u) break; 31 } 32 } 33 } 34 void init(){ 35 int x,y; 36 for (int i=1;i<=n;i++) G[i].clear(); 37 for (int i=1;i<=m;i++){ 38 scanf("%d%d",&x,&y); 39 G[x].push_back(y); 40 } 41 dfs_clock=scc_cnt=0; 42 memset(sccno,0,sizeof(sccno)); 43 memset(pre,0,sizeof(pre)); 44 while (!s.empty()) s.pop(); 45 } 46 void DAG(){ 47 for (int i=1;i<=n;i++) 48 if (!pre[i]) tarjan(i); 49 for (int i=1;i<=scc_cnt;i++) newnode[i].clear(); 50 memset(into,0,sizeof(into)); 51 for (int i=1;i<=n;i++) 52 for (int j=0;j<G[i].size();j++) 53 if (sccno[G[i][j]]!=sccno[i]){ 54 newnode[sccno[i]].push_back(sccno[G[i][j]]); 55 into[sccno[G[i][j]]]++; 56 } 57 } 58 void dfs(int u,int fa){ 59 for (int i=0;i<newnode[u].size();i++){ 60 int v=newnode[u][i]; 61 if (v!=fa) {ans++; dfs(v,u); break; } 62 } 63 } 64 int main(){ 65 int T; 66 scanf("%d",&T); 67 while (T--){ 68 scanf("%d%d",&n,&m); 69 init();//初始化 70 DAG();//tarjan求强联通分量并缩点 71 ans=1; 72 for (int i=1;i<=scc_cnt;i++) 73 if (into[i]==0) {dfs(i,-1); break;}//判断起始点出发的链长 74 if (ans==scc_cnt) printf("yes\n"); 75 else printf("no\n"); 76 } 77 return 0; 78 }