uva 11324 The Largest Clique
vjudge 上题目链接:uva 11324
scc + dp,根据大白书上的思路:" 同一个强连通分量中的点要么都选,要么不选。把强连通分量收缩点后得到SCC图,让每个SCC结点的权等于它的结点数,则题目转化为求 SCC 图上权最大的路径。由于 SCC 图是一个 DAG, 可以用动态规划求解。"
一开始我理解成了求所有结点的权值和,后来才明白所求的结果一定是 scc 上一条路径来的,即不能有任何分叉路径。我的代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int N = 1003; 7 8 vector<int> G[N], G2[N]; 9 bool vis[N]; 10 int sccno[N], scc_cnt, p[N]; 11 vector<int> S; 12 13 void dfs(int x) { 14 vis[x] = 1; 15 for(int i = 0; i < G[x].size(); ++i) 16 if(!vis[G[x][i]]) dfs(G[x][i]); 17 S.push_back(x); 18 } 19 20 void dfs2(int x, int &num) { 21 if(sccno[x]) return ; 22 sccno[x] = scc_cnt; 23 ++num; 24 for(int i = 0; i < G2[x].size(); ++i) 25 dfs2(G2[x][i], num); 26 } 27 28 void find_scc(int n) { 29 memset(vis, 0, sizeof vis); 30 S.clear(); 31 for(int i = 0; i < n; ++i) 32 if(!vis[i]) dfs(i); 33 34 memset(sccno, 0, sizeof sccno); 35 memset(p, 0, sizeof p); 36 scc_cnt = 0; 37 for(int i = n - 1; i >= 0; --i) 38 if(!sccno[S[i]]) { 39 ++scc_cnt; 40 int num = 0; 41 dfs2(S[i], num); 42 p[scc_cnt] = num; 43 } 44 } 45 46 vector<int> d[N]; 47 void debug(int n) { 48 for(int i = 0; i < n; ++i) 49 d[i].clear(); 50 for(int i = 0; i < n; ++i) 51 d[sccno[i]].push_back(i); 52 53 for(int u = 1; u <= scc_cnt; ++u) { 54 printf("sccno[%d]: ",u); 55 for(int i = 0; i < d[u].size(); ++i) 56 printf("%d ",d[u][i] + 1); 57 printf(" num = %d p[%d] = %d ", d[u].size(), u, p[u]); 58 } 59 } 60 61 62 vector<int> g3[N]; 63 int node(int x) { 64 if(vis[x]) return p[x]; 65 vis[x] = 1; 66 int Max = 0; 67 for(int i = 0; i < g3[x].size(); ++i) 68 Max = max(Max, node(g3[x][i])); 69 return p[x] += Max; 70 } 71 72 void new_graph(int n) { 73 for(int i = 0; i <= n; ++i) 74 g3[i].clear(); 75 for(int u = 0; u < n; ++u) 76 for(int i = 0; i < G[u].size(); ++i) { 77 int v = G[u][i]; 78 if(sccno[u] != sccno[v]) g3[sccno[u]].push_back(sccno[v]); 79 } 80 memset(vis, 0, sizeof vis); 81 int ans = 0; 82 for(int i = 1; i <= scc_cnt; ++i) 83 ans = max(ans, node(i)); 84 printf("%d ",ans); 85 } 86 87 int main() { 88 int t,n,m,x,y; 89 scanf("%d",&t); 90 while(t--) { 91 scanf("%d %d",&n,&m); 92 for(int i = 0; i < n; ++i) { 93 G[i].clear(); 94 G2[i].clear(); 95 } 96 while(m--) { 97 scanf("%d %d",&x,&y); 98 --x; --y; 99 G[x].push_back(y); 100 G2[y].push_back(x); 101 } 102 find_scc(n); 103 // debug(n); 104 new_graph(n); 105 } 106 return 0; 107 }