ZOJ 3795:Grouping(缩点+最长路)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5303
题意:有n个人m条边,每条边有一个u,v,代表u的年龄大于等于v,现在要将这n个人分成x个组,组内的人的年龄不能够直接或者间接比较,问最少可以分成多少组。
思路:一开始没看清题意,直接拓扑排序做了。后来听师兄说会有环,年龄大于等于,如果有环代表这里面的年龄相等,那么环里面的人都是每个人一组,缩完点之后那个点的长度就是点的人数,然后用DP最长路做。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <stack> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 #define N 100010 15 struct Edge { 16 int v, nxt; 17 } edge[N*3], edg[N*3]; 18 int cnt[N], dp[N], head[N], hea[N], tott, tot, tim, vis[N], deg[N], dfn[N], low[N], belong[N], num; 19 stack<int> sta; 20 21 void Add(int u, int v) { 22 edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++; 23 } 24 25 void add(int u, int v) { 26 edg[tott].v = v; edg[tott].nxt = hea[u]; hea[u] = tott++; 27 } 28 29 void tarjan(int u) { 30 dfn[u] = low[u] = ++tim; 31 sta.push(u); vis[u] = 1; 32 for(int i = head[u]; ~i; i = edge[i].nxt) { 33 Edge &e = edge[i]; 34 if(!dfn[e.v]) { 35 tarjan(e.v); 36 if(low[e.v] < low[u]) low[u] = low[e.v]; 37 } else if(vis[e.v] && dfn[e.v] < low[u]) low[u] = dfn[e.v]; 38 } 39 if(low[u] == dfn[u]) { 40 ++num; int v = -1; 41 cnt[num] = 0; 42 while(v != u) { 43 v = sta.top(); sta.pop(); 44 belong[v] = num; 45 cnt[num]++; 46 vis[v] = 0; 47 } 48 } 49 } 50 51 int DFS(int u) { 52 if(dp[u]) return dp[u]; 53 int ans = cnt[u]; 54 for(int i = hea[u]; ~i; i = edg[i].nxt) { 55 int v = edg[i].v; 56 ans = max(ans, DFS(v) + cnt[u]); 57 } 58 return dp[u] = ans; 59 } 60 61 int main() { 62 int n, m; 63 while(~scanf("%d%d", &n, &m)) { 64 memset(head, -1, sizeof(head)); 65 memset(hea, -1, sizeof(hea)); 66 memset(dfn, 0, sizeof(dfn)); 67 memset(dp, 0, sizeof(dp)); 68 tot = num = tott = tim = 0; 69 int u, v; 70 for(int i = 0; i < m; i++) { 71 scanf("%d%d", &u, &v); 72 Add(u, v); 73 } 74 for(int i = 1; i <= n; i++) 75 if(!dfn[i]) tarjan(i); 76 for(int u = 1; u <= n; u++) { 77 for(int i = head[u]; ~i; i = edge[i].nxt) { 78 int v = edge[i].v; 79 if(belong[u] != belong[v]) { 80 add(belong[u], belong[v]); 81 } 82 } 83 } 84 int ans = 0; 85 for(int i = 1; i <= num; i++) 86 ans = max(ans, DFS(i)); 87 printf("%d\n", ans); 88 } 89 return 0; 90 }