Codeforces 9E Interesting Graph and Apples(并查集)

来源:互联网 发布:excel数组公式怎么用 编辑:程序博客网 时间:2024/04/29 04:14

题意:

大致就是给你n个点,这n个点之间有m条边相连,问能不能再添加几条边,使这n个点刚好能围成一个圈.

因为是无向图,判断能否成一个圈,也就是一个始祖,所以用了并查集。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int mn=55;int degree[mn];//记录顶点的度数int n,m,ansop;int father[mn];struct node{    int u,v;} op[6000];//记录添加的边void  init(){    int i;    for(i=1; i <=n ; i++)        father[i] = i;}int find(int x){    int r=x;    while(r!=father[r])        r=father[r];    int i=x,j;    while(i!=r)    {        j=father[i];        father[i]=r;        i=j;    }    return r;}void Union(int a,int b){    int at =find(a);    int bt= find(b);    if(at==bt) return;    else        father[at] = father[bt];}bool ans()                           {    for(int i=1; i<=n; i++)    {        if(degree[i]<2)        {            for(int j=i+1; j<=n; j++)                if(degree[j]<2&&find(i)!=find(j))                {                    Union(i,j);                    op[ansop].u=i;                    op[ansop].v=j;                    ansop++;                    degree[i]++;                    degree[j]++;                    break;                }            if(degree[i]<2)            {                for(int j=i+1; j<=n; j++)                    if(degree[j]<2&&find(i)!=find(j))                    {                        Union(i,j);                        op[ansop].u=i;                        op[ansop].v=j;                        ansop++;                        degree[i]++;                        degree[j]++;                        break;                    }            }        }    }    int cot=0;    for(int i=1; i<=n; i++)    {        if(degree[i]!=1&&degree[i]!=2) return false;        if(degree[i]==1) cot++;    }    if(cot==2) return true;    else return false;}int main(){    int x,y;    bool sign;    bool flag;    while(cin>>n>>m)    {        if(n==1&&m==0)                         //特判,当只有1个点和0跳边        {            cout<<"YES"<<endl<<"1"<<endl<<"1 1"<<endl;            continue;        }        int tmp=0;        sign=flag=0;        init();        ansop=0;        memset(degree,0,sizeof(degree));        while(m--)        {            cin>>x>>y;            degree[x]++;            degree[y]++;            if(find(x)==find(y)) flag=1;//如果形成环,标记为1            Union(x,y);        }        for(int i=1; i<=n; i++)                  tmp=max(degree[i],tmp);        if(tmp>2)                        //如果有度数大于2的,肯定是NO        {            cout<<"NO"<<endl;            continue;        }        if(flag)                         //若有原图中有环,进行讨论        {            int t=find(1);            for(int i=2; i<=n; i++)            {                if(t==find(i)&&degree[i]==2) continue;                else                {                    sign=1;                    break;                }            }            if(!sign) cout<<"YES"<<endl<<"0"<<endl;            else                cout<<"NO"<<endl;            continue;        }        if(ans())        {            int p[2],cot=0;            for(int i=1; i<=n; i++)                if(degree[i]==1) p[cot++]=i;            op[ansop].u=p[0];            op[ansop++].v=p[1];            cout<<"YES"<<endl;            cout<<ansop<<endl;            for(int i=0; i<ansop; i++)                cout<<op[i].u<<" "<<op[i].v<<endl;        }        else cout<<"NO"<<endl;    }    return 0;}


原创粉丝点击