• Codeforces 557D. Vitaly and Cycle(二分图判断)


    题目链接:https://codeforces.com/contest/557/problem/D

    题意:给出n个点,m条边无重边,无自环的无向图。问最少加几条边可以找到一个奇环,并且求出加最少边数的方案数。

    思路:最少的奇环当然是3个点,3条边构成的奇环了。

    显然加最少的边数就是0,1,2,3其中一个。

    1.当边数0时,最少加边数为3,方案数就是n个点取3个连环( c(3,n)=n*(n-1)*(n-2)/2/3)

    2.当每个点最多有一条边时,最少加边数为2,方案数  边数*(n-2)

    3.因为二分图一定不含奇环的,判断是否是二分图,不是二分图,则一定有奇环,最少加边数就是0,方案数自然为1。

    4.当为二分图时,最少加边数为1, 染色判断二分图后,同种颜色的点连边会构成奇环,所以方案数就 是颜色相同点 连边  方案数

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=1e5+10;
    ll n,m;
    vector<int> ve[maxn];
    int nume[maxn],nump[maxn],sump[maxn];
    //nume[i]i点出度,nump[i]第i个连通图白点个数,sump[i]第i个连通图总点数 
    int color[maxn];
    
    bool dfs(int x,int c,int scc)//判断是否是二分图,并存储每个连通图的点数和白点的个数 
    {
        sump[scc]++;
        color[x]=c;
        if(color[x]==1)
            nump[scc]++;
        int s=ve[x].size();
        for(int i=0;i<s;i++)
        {
            if(color[ve[x][i]]==c)
                return false;
            if(color[ve[x][i]]==0&&!dfs(ve[x][i],-c,scc))
                return false;
        }
        return true;
    }
    
    int main()
    {
        int u,v;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            ve[u].push_back(v);
            ve[v].push_back(u);
            nume[u]++;//出度,用于下面就算是否只连一条边 
            nume[v]++;    
        }    
        if(m==0)//1.边数为0时 
        {
            printf("3 %lld
    ",n*(n-1)*(n-2)/3/2);
            return 0;
        }
        ll cnt=0;//计算每个点只有一条边的数量,也起到标记作用 
        for(int i=1;i<=n;i++)
        {
            if(nume[i]>1)//不是每个点只有一条边  
            {
                cnt=-1;
                break;
            }
            else if(nume[i]==1)
                cnt++;
        }
        if(cnt!=-1)//2.每个点最多有一条边时
        {
            printf("2 %lld
    ",cnt/2*(n-2));    
            return 0;
        }    
        int flag=0,scc=0;//flag标记是否是二分图,scc计算连通图的个数 
        for(int i=1;i<=n;i++)
        {
            if(!color[i])
            {
                if(!dfs(i,1,scc++))//不是二分图,有奇环 
                {
                    flag=1;
                    break;
                }    
            }
        }
        if(flag)//3.//不是二分图,有奇环
            printf("0 1
    ");
        else//是二分图 
        {
            ll ans=0;
            for(int i=0;i<scc;i++)//对于每个连通块,方案数+=白点选2个+黑点选2个 
                ans+=(ll)nump[i]*(nump[i]-1)/2+(ll)(sump[i]-nump[i])*(sump[i]-nump[i]-1)/2;
            printf("1 %lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Maven+SSM框架搭建【spring+springmvc+mybatis】
    [福大软工] W班 总成绩排行榜
    项目Beta冲刺团队随笔集
    45度炸队Alpha冲刺博客集
    SDN期末验收
    小黄衫——共同的荣誉
    软件工程实践总结作业
    SDN第五次上机作业
    SDN第四次作业
    总结随笔
  • 原文地址:https://www.cnblogs.com/xiongtao/p/11973248.html
Copyright © 2020-2023  润新知