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 }

题目链接:http://poj.org/problem?id=2762

posted on 2015-03-31 01:36  xiao_xin  阅读(130)  评论(0编辑  收藏  举报

导航