Poj--2762(强连通分量,缩点,DAG最长链)

2014-10-14 21:44:18

思路:问一个图是否是单连通的。先对全图求一次SCC,可以知道每个SCC内的点都是单连通的,那么把每个SCC缩点构建出DAG之后再判断这个DAG是否单连通即可,方法是DAG动规找出最长链,如果最长链上的点个数等于SCC个数,那么DAG单连通。(因为如果最长链都不能覆盖所有点,那么必定有两个点之间是无法到达的)

  1 /*************************************************************************
  2     > File Name: 2762.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Tue 14 Oct 2014 07:42:48 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 1010;
 27 
 28 int T,n,m;
 29 int first[maxn],next[maxn * 6],ver[maxn * 6],ecnt;
 30 int low[maxn],dfn[maxn],sc[maxn],scnt,tot;
 31 int f1[maxn],n1[maxn * 6],v1[maxn * 6],e1;
 32 int dp[maxn];
 33 stack<int> S;
 34 
 35 void Add_edge(int u,int v){
 36     next[++ecnt] = first[u];
 37     ver[ecnt] = v;
 38     first[u] = ecnt;
 39 }
 40 
 41 void Init(){
 42     memset(first,-1,sizeof(first));
 43     memset(f1,-1,sizeof(f1));
 44     memset(dp,0,sizeof(dp));
 45     tot = ecnt = scnt = 0;
 46     e1 = 0;
 47 }
 48 
 49 void Dfs(int p){
 50     dfn[p] = low[p] = ++tot;
 51     S.push(p);
 52     for(int i = first[p]; i != -1; i = next[i]){
 53         int v = ver[i];
 54         if(!dfn[v]){
 55             Dfs(v);
 56             low[p] = min(low[p],low[v]);
 57         }
 58         else if(!sc[v]){
 59             low[p] = min(low[p],dfn[v]);
 60         }
 61     }
 62     if(low[p] == dfn[p]){
 63         ++scnt;
 64         while(1){
 65             int x = S.top();
 66             S.pop();
 67             sc[x] = scnt;
 68             if(x == p) break;
 69         }
 70     }
 71 }
 72 
 73 void Tarjan(){
 74     memset(dfn,0,sizeof(dfn));
 75     memset(low,0,sizeof(low));
 76     memset(sc,0,sizeof(sc));
 77     while(!S.empty()) S.pop();
 78     for(int i = 1; i <= n; ++i)
 79         if(!dfn[i]) Dfs(i);
 80 }
 81 
 82 void Add_edge1(int u,int v){
 83     n1[++e1] = f1[u];
 84     v1[e1] = v;
 85     f1[u] = e1;
 86 }
 87 
 88 int Solve(int p){
 89     if(p == 0) return 0;
 90     if(dp[p]) return dp[p];
 91     for(int i = f1[p]; i != -1; i = n1[i]){
 92         int v = v1[i];
 93         dp[p] = max(dp[p],Solve(v));
 94     }
 95     return dp[p] = dp[p] + 1;
 96 }
 97 
 98 int main(){
 99     int a,b;
100     scanf("%d",&T);
101     while(T--){
102         Init();
103         scanf("%d%d",&n,&m);
104         for(int i = 1; i <= m; ++i){
105             scanf("%d%d",&a,&b);
106             Add_edge(a,b);
107         }
108         Tarjan();
109         for(int k = 1; k <= n; ++k){
110             for(int i = first[k]; i != -1; i = next[i]){
111                 int v = ver[i];
112                 if(sc[k] != sc[v]){
113                     Add_edge1(sc[k],sc[v]);
114                 }
115             }
116         }
117         int ans = 0;
118         for(int i = 1; i <= scnt && ans < scnt; ++i)
119             ans = max(ans,Solve(i));
120         if(ans >= scnt) printf("Yes\n");
121         else printf("No\n");
122     }
123     return 0;
124 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4025284.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值