codeforces 557D. Vitaly and Cycle 二分图染色

题目链接

n个点, m条边, 问最少加几条边可以出现一个奇环, 在这种情况下, 有多少种加边的方式。

具体看代码解释

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define ll long long
 5 #define mk(x, y) make_pair(x, y)
 6 #define lson l, m, rt<<1
 7 #define mem(a) memset(a, 0, sizeof(a))
 8 #define rson m+1, r, rt<<1|1
 9 #define mem1(a) memset(a, -1, sizeof(a))
10 #define mem2(a) memset(a, 0x3f, sizeof(a))
11 #define rep(i, a, n) for(int i = a; i<n; i++)
12 #define ull unsigned long long
13 typedef pair<int, int> pll;
14 const double PI = acos(-1.0);
15 const double eps = 1e-8;
16 const int mod = 1e9+7;
17 const int inf = 1061109567;
18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
19 const int maxn = 1e5+5;
20 int de[maxn], white[maxn], black[maxn], color[maxn], head[maxn*2], num, flag;
21 struct node
22 {
23     int to, nextt;
24 }e[maxn*2];
25 void add(int u, int v) {
26     e[num].to = v;
27     e[num].nextt = head[u];
28     head[u] = num++;
29 }
30 void dfs(int u, int c, int s) {                 //每一个cnt代表一个联通块, c是颜色
31     color[u] = c;
32     if(c&1)
33         black[s]++;
34     else
35         white[s]++;
36     for(int i = head[u]; ~i; i = e[i].nextt) {
37         int v = e[i].to;
38         if(!color[v]) {                     
39             dfs(v, 3-c, s);
40         } else if(color[v]==color[u]) {         //这是本身就有奇环
41             flag = 1;
42         }
43     }
44 }
45 int main()
46 {
47     int n, m;
48     cin>>n>>m;
49     if(!m) {
50         cout<<3<<" "<<1ll*n*(n-1)*(n-2)/6;          //一条边也没有
51         return 0;
52     }
53     int x, y;
54     mem1(head);
55     for(int i = 1; i<=m; i++) {
56         scanf("%d%d", &x, &y);
57         de[x]++, de[y]++;
58         add(x, y);
59         add(y, x);
60         if(de[x]>1||de[y]>1) {
61             flag = 1;
62         }
63     }
64     if(!flag) {
65         cout<<2<<" "<<1ll*m*(n-2)<<endl;            //这种情况是有边, 但是所有的边都不相连
66         return 0;
67     }
68     flag = 0;
69     int cnt = 0;
70     for(int i = 1; i<=n; i++) {
71         if(!color[i]) {
72             dfs(i, 1, ++cnt);                   
73         }
74         if(flag) {
75             puts("0 1");
76             return 0;                           //本身就有奇环
77         }
78     }
79     ll ans = 0;
80     for(int i = 1; i<=cnt; i++) {
81         ans += 1ll*(white[i]-1)*white[i]+1ll*black[i]*(black[i]-1);         //每一个联通块里面的种数累加。
82     }
83     cout<<1<<" "<<ans/2<<endl;
84     return 0;
85 }

 

posted on 2015-12-23 16:36  yohaha  阅读(172)  评论(0编辑  收藏  举报

导航