您的位置:首页 > 其它

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

2015-12-23 16:36 369 查看
题目链接

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

具体看代码解释

#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 1e5+5;
int de[maxn], white[maxn], black[maxn], color[maxn], head[maxn*2], num, flag;
struct node
{
int to, nextt;
}e[maxn*2];
void add(int u, int v) {
e[num].to = v;
e[num].nextt = head[u];
head[u] = num++;
}
void dfs(int u, int c, int s) {                 //每一个cnt代表一个联通块, c是颜色
color[u] = c;
if(c&1)
black[s]++;
else
white[s]++;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(!color[v]) {
dfs(v, 3-c, s);
} else if(color[v]==color[u]) {         //这是本身就有奇环
flag = 1;
}
}
}
int main()
{
int n, m;
cin>>n>>m;
if(!m) {
cout<<3<<" "<<1ll*n*(n-1)*(n-2)/6;          //一条边也没有
return 0;
}
int x, y;
mem1(head);
for(int i = 1; i<=m; i++) {
scanf("%d%d", &x, &y);
de[x]++, de[y]++;
add(x, y);
add(y, x);
if(de[x]>1||de[y]>1) {
flag = 1;
}
}
if(!flag) {
cout<<2<<" "<<1ll*m*(n-2)<<endl;            //这种情况是有边, 但是所有的边都不相连
return 0;
}
flag = 0;
int cnt = 0;
for(int i = 1; i<=n; i++) {
if(!color[i]) {
dfs(i, 1, ++cnt);
}
if(flag) {
puts("0 1");
return 0;                           //本身就有奇环
}
}
ll ans = 0;
for(int i = 1; i<=cnt; i++) {
ans += 1ll*(white[i]-1)*white[i]+1ll*black[i]*(black[i]-1);         //每一个联通块里面的种数累加。
}
cout<<1<<" "<<ans/2<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: