BZOJ1093 [ZJOI2007]最大半连通子图

 1 /**************************************************************
2     Problem: 1093
3     User: rausen
4     Language: C++
5     Result: Accepted
6     Time:1604 ms
7     Memory:31220 kb
8 ****************************************************************/
9
10 #include <cstdio>
11 #include <algorithm>
12 #include <cstring>
13
14 using namespace std;
15 const int inf = (int) 1e8;
16 struct edges{
17     int from, to, next;
18 }e[2000005];
19
20 int first[100005],tot;
21 int dfn[100005], low[100005], w[100005], sum[100005];
22 int vis[100005], s[100005], f[100005], g[100005], F[100005];
23 int n, m, MOD, X, Y, ans, top, cnt, num, ANS;
24
25 void add_edge(int x, int y){
26     e[++tot].next = first[x];
27     first[x] = tot;
28     e[tot].from = x, e[tot].to = y;
29 }
30
31 void tarjan(int p){
32     dfn[p] = low[p] = ++cnt;
33     s[++top] = p;
34     vis[p] = 1;
35     int x, y;
36     for (x = first[p]; x; x = e[x].next){
37         y = e[x].to;
38         if (!vis[y]) tarjan(y);
39         if (vis[y] < 2)
40             low[p] = min(low[p], low[y]);
41     }
42     if (dfn[p] == low[p]){
43         ++num;
44         while (s[top + 1] != p){
45             int y = s[top--];
46             vis[y] = 2, w[y] = num;
47             ++sum[num];
48         }
49     }
50 }
51
52 void dfs(int p){
53     if (vis[p]) return;
54     vis[p] = inf;
55     int x, y;
56     for (int x = first[p]; x; x = e[x].next){
57         y = e[x].to;
58         if (vis[y] == p) continue;
59         vis[y] = p;
60         dfs(y);
61         if (f[p] < f[y])
62             f[p] = f[y], g[p] = g[y]; else
63         if (f[p] == f[y]) g[p] += g[y];
64     }
65     g[p] %= MOD;
66     f[p] += sum[p];
67     if (ans < f[p])
68         ans = f[p], ANS = g[p]; else
69     if (ans == f[p]) ANS += g[p], ANS %= MOD;
70 }
71
72 int main(){
73     scanf("%d%d%d", &n, &m, &MOD);
74     for (int i = 1; i <= m; ++i)
75         scanf("%d%d", &X, &Y), add_edge(X, Y);
76     for (int i = 1; i <= n; ++i)
77         if (!vis[i]) tarjan(i);
78
79     memset(first, 0, sizeof(first));
80     tot = 0;
81     for (int i = 1; i <= m; ++i){
82         X = e[i].from;
83         Y = e[i].to;
84         if (w[X] != w[Y]) add_edge(w[X], w[Y]);
85     }
86     memset(vis, 0, sizeof(vis));
87     for (int i = 1; i <= num; ++i)
88         if (!first[i]) g[i] = 1;
89     for (int i = 1; i <= num; ++i)
90         if (!vis[i]) dfs(i);
91     printf("%d\n%d\n", ans, ANS % MOD);
92     return 0;
93 }
View Code

(p.s. 各种压代码+卡内存此题status终于上了前两页。。。)

posted on 2014-10-06 22:30  Xs酱~  阅读(...)  评论(...编辑  收藏