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