Uva--11324(强连通分量,缩点,DAG动规)

2014-10-14 19:19:50

思路:这题取名为最大团(表示不知道何物,以后学QAQ)。其实就是求一次全图的所有强连通分量,然后缩点。缩点的方法请教了通神,方法:做一次tarjan后,再扫一遍原图中的所有边,如果这条边所连接的两个点在同个scc中则不用连边,否则在两个scc间建一条有向边(这里的边要与原图边区分开来)。然后就形成了一个带点权的DAG,每个点的点权即是该点所代表的scc内点的个数,做一次DAG动规求出路径上的最大点权和,就是答案。

  1 /*************************************************************************
  2     > File Name: 11324.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Tue 14 Oct 2014 04:39:08 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 const int maxn1 = 50010;
 28 
 29 int T,n,m;
 30 int first[maxn],next[maxn1],ver[maxn1],ecnt;
 31 int low[maxn],dfn[maxn],sc[maxn],scn[maxn],tot,scnt;
 32 int first1[maxn],next1[maxn],ver1[maxn],ecnt1;
 33 int ans,dp[maxn];
 34 stack<int> S;
 35 
 36 void Init(){
 37     memset(first,-1,sizeof(first));
 38     memset(first1,-1,sizeof(first1));
 39     memset(dp,0,sizeof(dp));
 40     ecnt = tot = scnt = 0;
 41     ecnt1 = 0;
 42 }
 43 
 44 void Add_edge(int u,int v){
 45     next[++ecnt] = first[u];
 46     ver[ecnt] = v;
 47     first[u] = ecnt;
 48 }
 49 
 50 void Add_edge1(int u,int v){
 51     next1[++ecnt1] = first1[u];
 52     ver1[ecnt1] = v;
 53     first1[u] = ecnt1;
 54 }
 55 
 56 void Dfs(int p){
 57     low[p] = dfn[p] = ++tot;
 58     S.push(p);
 59     for(int i = first[p]; i != -1; i = next[i]){
 60         int v = ver[i];
 61         if(!dfn[v]){
 62             Dfs(v);
 63             low[p] = min(low[p],low[v]);
 64         }
 65         else if(!sc[v]){
 66             low[p] = min(low[p],dfn[v]);
 67         }
 68     }
 69     if(low[p] == dfn[p]){
 70         ++scnt;
 71         while(1){
 72             int x = S.top();
 73             S.pop();
 74             sc[x] = scnt;
 75             scn[scnt]++;
 76             if(x == p) break;
 77         }
 78     }
 79 }
 80 
 81 void Tarjan(){
 82     memset(low,0,sizeof(low));
 83     memset(dfn,0,sizeof(dfn));
 84     memset(sc,0,sizeof(sc));
 85     memset(scn,0,sizeof(scn));
 86     while(!S.empty()) S.pop();
 87     for(int i = 1; i <= n; ++i)
 88         if(!dfn[i]) Dfs(i);
 89 }
 90 
 91 int Solve(int p){
 92     if(dp[p]) return dp[p];
 93     for(int i = first1[p]; i != -1; i = next1[i]){
 94         int v = ver1[i];
 95         dp[p] = max(dp[p],Solve(v));
 96     }
 97     return dp[p] = dp[p] + scn[p];
 98 }
 99 
100 int main(){
101     int a,b;
102     scanf("%d",&T);
103     while(T--){
104         Init();
105         scanf("%d%d",&n,&m);
106         for(int i = 1; i <= m; ++i){
107             scanf("%d%d",&a,&b);
108             Add_edge(a,b);
109         }
110         Tarjan();
111         for(int k = 1; k <= n; ++k){
112             for(int i = first[k]; i != -1; i = next[i]){
113                 int v = ver[i];
114                 if(sc[k] != sc[v]){
115                     Add_edge1(sc[k],sc[v]);
116                 }
117             }
118         }
119         ans = 0;
120         for(int i = 1; i <= scnt; ++i)
121             ans = max(ans,Solve(i));
122         printf("%d\n",ans);
123     }
124     return 0;
125 }
126         

 

posted @ 2014-10-14 19:28  Naturain  阅读(529)  评论(0编辑  收藏  举报