给定一个图,求一个节点数目最多的团,对于其中任意两个节点u,v至少存在一条这样的路径使得u到v,或者v到u。
分析: 先求出强连通分量,然后缩点,构成一个scc图,然后求一条最长的路,每个节点的权重即为该强连通分量的节点数目,由于是DAG, 所以可以用dp或者spfa,一开始用记忆化搜索竟然TLE,想也想不通,后来改成spfa,以0为起点,然后求出距离0的最大距离。
spfa:
1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <climits> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <stack> 9 #include <map> 10 #include <cmath> 11 #include <vector> 12 #include <queue> 13 #include <algorithm> 14 #define esp 1e-6 15 #define pi acos(-1.0) 16 #define pb push_back 17 #define mp(a, b) make_pair((a), (b)) 18 #define in freopen("in.txt", "r", stdin); 19 #define out freopen("out.txt", "w", stdout); 20 #define print(a) printf("%d ",(a)); 21 #define bug puts("********))))))"); 22 #define stop system("pause"); 23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) 24 25 #define inf 0x0f0f0f0f 26 27 using namespace std; 28 typedef long long LL; 29 typedef vector<int> VI; 30 typedef pair<int, int> pii; 31 typedef vector<pii,int> VII; 32 typedef vector<int>:: iterator IT; 33 const int maxn = 5000; 34 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt; 35 int a[maxn], dp[maxn], dis[maxn], inq[maxn]; 36 VI g[maxn], G[maxn]; 37 stack<int> S; 38 void dfs(int u) 39 { 40 S.push(u); 41 lowlink[u] = pre[u] = ++dfs_clock; 42 for(int i = 0; i < g[u].size(); i++) 43 { 44 int v = g[u][i]; 45 if(!pre[v]) 46 { 47 dfs(v); 48 lowlink[u] = min(lowlink[u], lowlink[v]); 49 } 50 else if(!sccno[v]) 51 { 52 lowlink[u] = min(lowlink[u], pre[v]); 53 } 54 } 55 int cnt= 0; 56 if(lowlink[u] == pre[u]) 57 { 58 scc_cnt++; 59 for(;;) 60 { 61 int x = S.top(); 62 S.pop(); 63 cnt++; 64 sccno[x] = scc_cnt; 65 if(x == u) 66 { 67 a[scc_cnt] = cnt; 68 break; 69 } 70 } 71 } 72 } 73 void find_scc(int n) 74 { 75 memset(pre, 0, sizeof(pre)); 76 memset(sccno, 0, sizeof(sccno)); 77 78 dfs_clock = scc_cnt = 0; 79 for(int i = 0; i < n; i++) 80 if(!pre[i]) dfs(i); 81 } 82 void spfa(void) 83 { 84 memset(inq, 0, sizeof(inq)); 85 memset(dis, 0, sizeof(dis)); 86 queue<int> q; 87 inq[0] = 1; 88 q.push(0); 89 while(!q.empty()) 90 { 91 int u = q.front(); 92 q.pop(); 93 inq[u] = 0; 94 for(int i = 0; i < G[u].size(); i++) 95 { 96 int v = G[u][i]; 97 if(dis[v] < dis[u] + a[v]) 98 if(dis[v] = dis[u] + a[v], !inq[v]) 99 inq[v] = 1, q.push(v); 100 } 101 } 102 } 103 int main(void) 104 { 105 int n, m; 106 int T; 107 for(int t = scanf("%d", &T); t <= T; t++) 108 { 109 for(int i = 0; i < maxn; i++) 110 g[i].clear(), G[i].clear(); 111 scanf("%d%d", &n, &m); 112 memset(a, 0, sizeof(a)); 113 while(m--) 114 { 115 int u, v; 116 scanf("%d%d", &u, &v); 117 u--, v--; 118 g[u].pb(v); 119 } 120 find_scc(n); 121 for(int u = 0; u < n; u++) 122 for(int i = 0; i < g[u].size(); i++) 123 { 124 int v = g[u][i]; 125 if(sccno[v] != sccno[u]) 126 G[sccno[u]].pb(sccno[v]); 127 } 128 for(int i = 1; i <= scc_cnt; i++) 129 G[0].pb(i); 130 spfa(); 131 int ans = 0; 132 for(int i = 1; i <= scc_cnt; i++) 133 ans = max(ans, dis[i]); 134 printf("%d ", ans); 135 } 136 return 0; 137 }
下面是dp代码,一开始用的邻接矩阵存储关系图,后来改成邻接表果断过了,以后要注意了,尽量用邻接表
1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <climits> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <stack> 9 #include <map> 10 #include <cmath> 11 #include <vector> 12 #include <queue> 13 #include <algorithm> 14 #define esp 1e-6 15 #define pi acos(-1.0) 16 #define pb push_back 17 #define mp(a, b) make_pair((a), (b)) 18 #define in freopen("in.txt", "r", stdin); 19 #define out freopen("out.txt", "w", stdout); 20 #define print(a) printf("%d ",(a)); 21 #define bug puts("********))))))"); 22 #define stop system("pause"); 23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) 24 25 #define inf 0x0f0f0f0f 26 27 using namespace std; 28 typedef long long LL; 29 typedef vector<int> VI; 30 typedef pair<int, int> pii; 31 typedef vector<pii,int> VII; 32 typedef vector<int>:: iterator IT; 33 const int maxn = 5000; 34 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt; 35 int a[maxn], dp[maxn], dis[maxn], inq[maxn]; 36 VI g[maxn], G[maxn]; 37 stack<int> S; 38 void dfs(int u) 39 { 40 S.push(u); 41 lowlink[u] = pre[u] = ++dfs_clock; 42 for(int i = 0; i < g[u].size(); i++) 43 { 44 int v = g[u][i]; 45 if(!pre[v]) 46 { 47 dfs(v); 48 lowlink[u] = min(lowlink[u], lowlink[v]); 49 } 50 else if(!sccno[v]) 51 { 52 lowlink[u] = min(lowlink[u], pre[v]); 53 } 54 } 55 int cnt= 0; 56 if(lowlink[u] == pre[u]) 57 { 58 scc_cnt++; 59 for(;;) 60 { 61 int x = S.top(); 62 S.pop(); 63 cnt++; 64 sccno[x] = scc_cnt; 65 if(x == u) 66 { 67 a[scc_cnt] = cnt; 68 break; 69 } 70 } 71 } 72 } 73 void find_scc(int n) 74 { 75 memset(pre, 0, sizeof(pre)); 76 memset(sccno, 0, sizeof(sccno)); 77 78 dfs_clock = scc_cnt = 0; 79 for(int i = 0; i < n; i++) 80 if(!pre[i]) dfs(i); 81 } 82 void spfa(void) 83 { 84 memset(inq, 0, sizeof(inq)); 85 memset(dis, 0, sizeof(dis)); 86 queue<int> q; 87 inq[0] = 1; 88 q.push(0); 89 while(!q.empty()) 90 { 91 int u = q.front(); 92 q.pop(); 93 inq[u] = 0; 94 for(int i = 0; i < G[u].size(); i++) 95 { 96 int v = G[u][i]; 97 if(dis[v] < dis[u] + a[v]) 98 if(dis[v] = dis[u] + a[v], !inq[v]) 99 inq[v] = 1, q.push(v); 100 } 101 } 102 } 103 int main(void) 104 { 105 int n, m; 106 int T; 107 for(int t = scanf("%d", &T); t <= T; t++) 108 { 109 for(int i = 0; i < maxn; i++) 110 g[i].clear(), G[i].clear(); 111 scanf("%d%d", &n, &m); 112 memset(a, 0, sizeof(a)); 113 while(m--) 114 { 115 int u, v; 116 scanf("%d%d", &u, &v); 117 u--, v--; 118 g[u].pb(v); 119 } 120 find_scc(n); 121 for(int u = 0; u < n; u++) 122 for(int i = 0; i < g[u].size(); i++) 123 { 124 int v = g[u][i]; 125 if(sccno[v] != sccno[u]) 126 G[sccno[u]].pb(sccno[v]); 127 } 128 for(int i = 1; i <= scc_cnt; i++) 129 G[0].pb(i); 130 spfa(); 131 int ans = 0; 132 for(int i = 1; i <= scc_cnt; i++) 133 ans = max(ans, dis[i]); 134 printf("%d ", ans); 135 } 136 return 0; 137 }