UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP
题目链接:https://vjudge.net/problem/UVA-11324
题解:
题意:给出一张有向图,求一个结点数最大的结点集,使得任意两个结点u、v,要么u能到达v, 要么v能到达u(u和v也可以互相到达)。
1.可知在一个强连通分量中,任意两个点都可以互相到达。那么我们就对每个强连通分量进行缩点,并记录每个分量的结点个数。
2.缩点之后,就是一张有向无环图了,这时就转化为求:从有向无环图中找出一条权值之和最大的路径。简单的记忆化搜索即可实现。
前向星建图 + 前向星重建:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXM = 5e4+10; 18 const int MAXN = 1e3+10; 19 20 struct Edge 21 { 22 int to, next; 23 }edge[MAXM], edge0[MAXM]; //edge为初始图, edge0为重建图 24 int tot, head[MAXN], tot0, head0[MAXN]; 25 26 int Index, dfn[MAXN], low[MAXN]; 27 int top, Stack[MAXN], instack[MAXN]; 28 int scc, belong[MAXN], num[MAXN]; 29 int dp[MAXN]; 30 31 void addedge(int u, int v, Edge edge[], int head[], int &tot) 32 { 33 edge[tot].to = v; 34 edge[tot].next = head[u]; 35 head[u] = tot++; 36 } 37 38 void Tarjan(int u) 39 { 40 dfn[u] = low[u] = ++Index; 41 Stack[top++] = u; 42 instack[u] = true; 43 for(int i = head[u]; i!=-1; i = edge[i].next) 44 { 45 int v = edge[i].to; 46 if(!dfn[v]) 47 { 48 Tarjan(v); 49 low[u] = min(low[u], low[v]); 50 } 51 else if(instack[v]) 52 low[u] = min(low[u], dfn[v]); 53 } 54 55 if(dfn[u]==low[u]) 56 { 57 int v; 58 scc++; 59 do 60 { 61 v = Stack[--top]; 62 instack[v] = false; 63 belong[v] = scc; 64 num[scc]++; 65 }while(v!=u); 66 } 67 } 68 69 int dfs(int u) 70 { 71 if(dp[u]!=-1) return dp[u]; 72 dp[u] = num[u]; 73 for(int i = head0[u]; i!=-1; i = edge0[i].next) 74 { 75 int v = edge0[i].to; 76 dp[u] = max(dp[u], num[u]+dfs(v)); 77 } 78 return dp[u]; 79 } 80 81 void init() 82 { 83 tot = tot0 = 0; 84 memset(head, -1, sizeof(head)); 85 memset(head0, -1, sizeof(head0)); 86 87 Index = top = 0; 88 memset(dfn, 0, sizeof(dfn)); 89 memset(low, 0, sizeof(low)); 90 memset(instack, 0, sizeof(instack)); 91 92 scc = 0; 93 memset(num, 0, sizeof(num)); 94 memset(dp, -1, sizeof(dp)); 95 } 96 97 int main() 98 { 99 int n, m, T; 100 scanf("%d", &T); 101 while(T--) 102 { 103 scanf("%d%d", &n, &m); 104 init(); 105 for(int i = 1; i<=m; i++) 106 { 107 int u, v; 108 scanf("%d%d", &u, &v); 109 addedge(u, v, edge, head, tot); 110 } 111 112 for(int i = 1; i<=n; i++) 113 if(!dfn[i]) 114 Tarjan(i); 115 116 for(int u = 1; u<=n; u++) //重建建图 117 for(int i = head[u]; i!=-1; i = edge[i].next) 118 { 119 int tmpu = belong[u]; 120 int tmpv = belong[edge[i].to]; 121 if(tmpu!=tmpv) 122 addedge(tmpu, tmpv, edge0, head0, tot0); 123 } 124 125 int ans = 0; 126 for(int i = 1; i<=scc; i++) 127 if(dp[i]==-1) 128 ans = max(ans, dfs(i)); 129 130 printf("%d\n", ans); 131 } 132 }
前向星建图 + vector重建:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const int MAXM = 5e4+10; 17 const int MAXN = 1e3+10; 18 19 struct Edge 20 { 21 int to, next; 22 }edge[MAXM]; 23 int tot, head[MAXN]; 24 vector<int>g[MAXN]; 25 26 int Index, dfn[MAXN], low[MAXN]; 27 int top, Stack[MAXN], instack[MAXN]; 28 int scc, belong[MAXN], num[MAXN]; 29 int dp[MAXN]; 30 31 void addedge(int u, int v) 32 { 33 edge[tot].to = v; 34 edge[tot].next = head[u]; 35 head[u] = tot++; 36 } 37 38 void Tarjan(int u) 39 { 40 dfn[u] = low[u] = ++Index; 41 Stack[top++] = u; 42 instack[u] = true; 43 for(int i = head[u]; i!=-1; i = edge[i].next) 44 { 45 int v = edge[i].to; 46 if(!dfn[v]) 47 { 48 Tarjan(v); 49 low[u] = min(low[u], low[v]); 50 } 51 else if(instack[v]) 52 low[u] = min(low[u], dfn[v]); 53 } 54 55 if(dfn[u]==low[u]) 56 { 57 int v; 58 scc++; 59 do 60 { 61 v = Stack[--top]; 62 instack[v] = false; 63 belong[v] = scc; 64 num[scc]++; 65 }while(v!=u); 66 } 67 } 68 69 int dfs(int u) 70 { 71 if(dp[u]!=-1) return dp[u]; 72 dp[u] = num[u]; 73 for(int i = 0; i<g[u].size(); i++) 74 { 75 int v = g[u][i]; 76 dp[u] = max(dp[u], num[u]+dfs(v)); 77 } 78 return dp[u]; 79 } 80 81 void init(int n) 82 { 83 tot = 0; 84 memset(head, -1, sizeof(head)); 85 86 Index = top = 0; 87 memset(dfn, 0, sizeof(dfn)); 88 memset(low, 0, sizeof(low)); 89 memset(instack, 0, sizeof(instack)); 90 91 scc = 0; 92 memset(num, 0, sizeof(num)); 93 memset(dp, -1, sizeof(dp)); 94 for(int i = 1; i<=n; i++) 95 g[i].clear(); 96 } 97 98 int main() 99 { 100 int n, m, T; 101 scanf("%d", &T); 102 while(T--) 103 { 104 scanf("%d%d", &n, &m); 105 init(n); 106 for(int i = 1; i<=m; i++) 107 { 108 int u, v; 109 scanf("%d%d", &u, &v); 110 addedge(u, v); 111 } 112 113 for(int i = 1; i<=n; i++) 114 if(!dfn[i]) 115 Tarjan(i); 116 117 for(int u = 1; u<=n; u++) 118 for(int i = head[u]; i!=-1; i = edge[i].next) 119 { 120 int tmpu = belong[u]; 121 int tmpv = belong[edge[i].to]; 122 if(tmpu!=tmpv) 123 g[tmpu].push_back(tmpv); 124 } 125 126 int ans = 0; 127 for(int i = 1; i<=scc; i++) 128 if(dp[i]==-1) 129 ans = max(ans, dfs(i)); 130 131 printf("%d\n", ans); 132 } 133 }
vector建图 + vector重建:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const int MAXN = 1e3+10; 17 18 vector<int>G[MAXN], g[MAXN]; 19 20 int Index, dfn[MAXN], low[MAXN]; 21 int top, Stack[MAXN], instack[MAXN]; 22 int scc, belong[MAXN], num[MAXN]; 23 int dp[MAXN]; 24 25 void Tarjan(int u) 26 { 27 dfn[u] = low[u] = ++Index; 28 Stack[top++] = u; 29 instack[u] = true; 30 for(int i = 0; i<G[u].size(); i++) 31 { 32 int v = G[u][i]; 33 if(!dfn[v]) 34 { 35 Tarjan(v); 36 low[u] = min(low[u], low[v]); 37 } 38 else if(instack[v]) 39 low[u] = min(low[u], dfn[v]); 40 } 41 42 if(dfn[u]==low[u]) 43 { 44 int v; 45 scc++; 46 do 47 { 48 v = Stack[--top]; 49 instack[v] = false; 50 belong[v] = scc; 51 num[scc]++; 52 }while(v!=u); 53 } 54 } 55 56 int dfs(int u) 57 { 58 if(dp[u]!=-1) return dp[u]; 59 dp[u] = num[u]; 60 for(int i = 0; i<g[u].size(); i++) 61 { 62 int v = g[u][i]; 63 dp[u] = max(dp[u], num[u]+dfs(v)); 64 } 65 return dp[u]; 66 } 67 68 void init(int n) 69 { 70 Index = top = 0; 71 memset(dfn, 0, sizeof(dfn)); 72 memset(low, 0, sizeof(low)); 73 memset(instack, 0, sizeof(instack)); 74 75 scc = 0; 76 memset(num, 0, sizeof(num)); 77 memset(dp, -1, sizeof(dp)); 78 for(int i = 1; i<=n; i++) 79 { 80 G[i].clear(); 81 g[i].clear(); 82 } 83 } 84 85 int main() 86 { 87 int n, m, T; 88 scanf("%d", &T); 89 while(T--) 90 { 91 scanf("%d%d", &n, &m); 92 init(n); 93 for(int i = 1; i<=m; i++) 94 { 95 int u, v; 96 scanf("%d%d", &u, &v); 97 G[u].push_back(v); 98 } 99 100 for(int i = 1; i<=n; i++) 101 if(!dfn[i]) 102 Tarjan(i); 103 104 for(int u = 1; u<=n; u++) 105 for(int i = 0; i<G[u].size(); i++) 106 { 107 int tmpu = belong[u]; 108 int tmpv = belong[G[u][i]]; 109 if(tmpu!=tmpv) 110 g[tmpu].push_back(tmpv); 111 } 112 113 int ans = 0; 114 for(int i = 1; i<=scc; i++) 115 if(dp[i]==-1) 116 ans = max(ans, dfs(i)); 117 118 printf("%d\n", ans); 119 } 120 }