Loading

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 }

 

posted @ 2017-01-11 20:27  Shadowdsp  阅读(334)  评论(0编辑  收藏  举报