码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #311 (Div. 2)

时间:2015-09-15 23:29:16      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

D

分4种情况讨论

1 不需要加边 , 就是说原本就有一个奇数环,我们只要跑一次二分图就好了

2 加一条边 , 也就是说存在大于等于3个点的联通块 我们对于这个联通块也跑一遍二分图, 可以知道图中所有的 同颜色染色中的点任意相连,都是一个奇数环,那么对于每个联通分量都有相应的数可以计算

3 加两条边,也就是说没有大于两个点的联通块存在,并且有两个点的联通块存在,答案也是可以计算出来的 e*(n-2)

4 加三条边 那么就可以知道每个联通块只有一个点,答案是 n*(n-1)*(n-2)/6;

技术分享
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=100005;
typedef long long LL;
int fa[maxn],Enum[maxn];
pair<int,int>e[maxn];
int fin(int a)
{
     return fa[a]=(a==fa[a])?a:fin( fa[a] );
}
bool solve1(LL n,int m)
{
    for(int i=0; i<m; i++)
        {
             int a=e[i].first,b=e[i].second;
             a=fin(a); b=fin(b);
             if(a==b)continue;
             Enum[a]+=Enum[b];
             fa[b]=a;
        }
    LL num1=0,num2=0;
    for(int i=1; i<=n; i++)
        {
            if(fa[i]!=i)continue;
            if(Enum[i]>2)return false;
            if(Enum[i]==1)num1++;
            else num2++;
        }
     if(num2==0){
        LL d=n*(n-1)*(n-2)/6;
        printf("3 %I64d\n",d);
     }else{
        LL d=num2*(n-2);
        printf("2 %I64d\n",d);
     }
     return true;
}
int H[maxn],nx[maxn*2],to[maxn*2],numofedg;
void add(int a, int b){
    numofedg++; to[numofedg]=b; nx[numofedg]=H[a]; H[a]=numofedg;
    numofedg++; to[numofedg]=a; nx[numofedg]=H[b]; H[b]=numofedg;
}
int color[maxn],num1,num2;
bool bipartite(int u)
{
    if(color[u]==1)num1++;
    else num2++;
    for(int i=H[u]; i; i=nx[i])
    {
          int v=to[i];
          if(color[u]==color[v])return false;
          if(color[v]==0){
            color[v]=3-color[u];
            if(bipartite(v)==false)return false;
          }
    }
    return true;
}
void solve2(LL n, int m)
{
     for(int i=0; i<m; i++){
        add(e[i].first,e[i].second);
     }
     LL ans=0;
     memset(color,0,sizeof(color));
     for(int i=1; i<=n; i++)
        {
             if(color[i]==0){
                color[i]=1;
                num1=num2=0;
                if(bipartite(i)==false){
                    printf("0 1\n");return ;
                }else{
                   ans+= 1LL*num1*(num1-1)/2 +1LL*num2*(num2-1)/2;
                }
             }
        }
        printf("1 %I64d\n",ans);
}
int main()
{
   int n,m;
   scanf("%d%d",&n,&m);
   numofedg=0;
   for(int i=1; i<=n; i++){fa[i]=i,Enum[i]=1; H[i]=0; }
   for(int i=0; i<m; i++)
    {
      scanf("%d%d",&e[i].first,&e[i].second);
    }
    if(solve1(n,m)){return 0;}
    solve2(n,m);
    return 0;
}
View Code

1

Codeforces Round #311 (Div. 2)

标签:

原文地址:http://www.cnblogs.com/Opaser/p/4811720.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!