Codeforces Round #311 (Div. 2) D. Vitaly and Cycle(二分图染色,奇环)

给定n个点,m条边.

求最少最要加几条边使图中存在奇环,且输出此时加边的方法种数

根据题意,只可能为

0:已经存在奇环,dfs搜到已经染色的且颜色相同

1:判断每个连通块里的 染色黑白色的个数

2 :某个点的 度 > 1

3:0条边

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<queue>
  4 #include<vector>
  5 #include<stack>
  6 #include<set>
  7 #include<string>
  8 #include<cstring>
  9 #include<math.h>
 10 #include<algorithm>
 11 #include<map>
 12
 13 #include<sstream>
 14 #include<ctype.h>
 15
 16 #define lson l,m,rt<<1
 17 #define rson m+1,r,rt<<1|1
 18
 19 typedef long long ll;
 20 using namespace std;
 21
 22 const int INF = 0x7f7f7f7f;
 23 const double PI = acos(-1.0);
 24 const int maxn = 1005;
 25 const int MOD = (int)1e9+7;
 26 #define LOCAL 0
 27 #define MOD 1000000007
 28
 29
 30 /*
 31 0 条边:0 1
 32 1 条边:
 33 2 条边 m*(n-2)
 34 3 条边 Cn3
 35 */
 36 int n,m;
 37 int degree[100005];
 38 vector<int> G[100005];
 39 int color[100005];
 40 int w[100005],b[100005];
 41 bool f,f0;
 42 int cnt; // 几个联通块
 43 void dfs(int u,int c,int num){
 44     color[u] = c;
 45     if(c & 1) w[num]++;
 46     else    b[num]++;
 47
 48     for(int i = 0 ; i < G[u].size() ; i ++){
 49         int v = G[u][i];
 50         if(!color[v]){
 51             dfs(v,3-c,num);
 52         }else{
 53             if(color[u] == color[v]){
 54                 f0 = true;
 55             }
 56         }
 57     }
 58 }
 59
 60 void solve(){
 61     // 3条边
 62     if(m == 0){
 63         printf("%d %I64d\n",3,1LL*n*(n-1)*(n-2)/6);
 64         return ;
 65     }
 66     for(int i = 0 ; i <= n ; i ++) G[i].clear();
 67     memset(degree,0,sizeof(degree));
 68     f = true;
 69     for(int i = 0 ; i < m ; i ++){
 70         int u,v;
 71         scanf("%d%d",&u,&v);
 72         G[u].push_back(v);    degree[u]++;
 73         G[v].push_back(u);    degree[v]++;
 74         if((degree[u] > 1) || (degree[v] > 1))  f = false;
 75     }
 76     // 2 条边
 77     if(f){
 78         printf("2 %I64d\n",1LL*m*(n-2));
 79         return ;
 80     }
 81
 82     f0 = false;
 83     cnt = 0;
 84     memset(color,0,sizeof(color));
 85     memset(w,0,sizeof(w));
 86     memset(b,0,sizeof(b));
 87     for(int i = 1 ; i <= n ; i ++){
 88         if(!color[i])
 89             dfs(i,1,cnt++);
 90     }
 91
 92     // 0条边
 93     if(f0){
 94         printf("0 1\n");
 95         return;
 96     }
 97
 98     //1条边
 99     ll ans = 0;
100     for(int i = 0 ; i < cnt ; i ++){
101         ans = ans + 1LL*w[i]*(w[i]-1)/2 + 1LL*b[i]*(b[i]-1)/2;
102     }
103     printf("1 %I64d\n",ans);
104     return ;
105 }
106 int main(){
107
108     while(scanf("%d%d",&n,&m) != EOF){
109         solve();
110     }
111
112     return 0;
113 }
时间: 2024-08-14 08:00:10

Codeforces Round #311 (Div. 2) D. Vitaly and Cycle(二分图染色,奇环)的相关文章

Codeforces Round #311 (Div. 2) A,B,C,D,E

A. Ilya and Diplomas 思路:水题了, 随随便便枚举一下,分情况讨论一下就OK了. code: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iostream> #include <cstring> #include <cmath> #define inf 1000000

Codeforces Round #311 (Div. 2)

D 分4种情况讨论 1 不需要加边 , 就是说原本就有一个奇数环,我们只要跑一次二分图就好了 2 加一条边 , 也就是说存在大于等于3个点的联通块 我们对于这个联通块也跑一遍二分图, 可以知道图中所有的 同颜色染色中的点任意相连,都是一个奇数环,那么对于每个联通分量都有相应的数可以计算 3 加两条边,也就是说没有大于两个点的联通块存在,并且有两个点的联通块存在,答案也是可以计算出来的 e*(n-2) 4 加三条边 那么就可以知道每个联通块只有一个点,答案是 n*(n-1)*(n-2)/6; #i

Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome (DP+字典树)

题目地址:传送门 先用dp求出所有的符合要求的半回文串,标记出来.然后构造字典树.然后再dfs一遍求出所有节点的子树和,最后搜一遍就能找出第k个来了. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map>

Codeforces Round #311 (Div. 2)--D(图

题意:给出一个图,问最少加多少条边能连出一个奇圈,还要求输出连边的方法种数. 思路:比赛的时候看了一下是图相关的就没多想,也没时间了,其实挺简单的,如果已经有奇圈,那么直接输出0 1,如果最多有两个点相连,那么就是(n-2)×m,就是每条边和另外的任意点连两条边,要么就是没有边,这个就是直接输出结果.. 稍微麻烦一点的是最后一种,联通块有多个点且没有奇圈,这时候需要把联通快黑白染色,同色的点相连就是一个奇圈,dfs的时候统计每个联通块中两种=颜色的个数即可. #include<bits/stdc

Codeforces Round #311 (Div. 2)A Ilya and Diplomas

[比赛链接]click here~~ [题目大意] n个人,获取一到三等文凭,每门文凭有大小范围,求最后文凭各颁发多少 [解题思路]直接枚举了, 看完题,赶紧写了一发代码,发现居然错过注册时间,系统提示不能提交代码,真是醉了~~,以后还是得提前注册: A题,比较简单: 代码: #include <iostream> #include <bits/stdc++.h> using namespace std; int main() { int n,m; int a1,a2; int b

2017-4-25-Train:Codeforces Round #311 (Div. 2)

A. Ilya and Diplomas(贪心) Soon a school Olympiad in Informatics will be held in Berland, n schoolchildren will participate there. At a meeting of the jury of the Olympiad it was decided that each of the n participants, depending on the results, will g

Codeforces Round #311 (Div. 2) B. Pasha and Tea

[题目链接]click here~~ [题目大意]给你n个boy,n个girl ,然后W表示茶壶的最大容量,然后n个茶杯,每个都有不同的容量,要求boy的茶杯里的茶水是girl的两倍,且boy和boy容量一样,girl和girl 容量一样,问如何倒茶,最大化总的茶量 [解题思路]这道题本来很简单,第一次读题没读明白,以为每个茶杯的茶水都倒满了,然后一想不就是拿最大的计算吗.一交,直接WA,然后仔细读题,发现,每个茶杯的茶水可以选择的倒(坑~啊),那么既然boy和boy,girl和girl的茶水一

Codeforces Round #284 (Div. 1) C. Array and Operations 二分图匹配

因为只有奇偶之间有操作, 可以看出是二分图, 然后拆质因子, 二分图最大匹配求答案就好啦. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #defin

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/