Codeforces 9E Interesting Graph and Apples(并查集)
2012-12-18 11:52
309 查看
题意:
大致就是给你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&°ree[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)&°ree[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;
}
大致就是给你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&°ree[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)&°ree[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;
}
相关文章推荐
- Codeforces 445B DZY Loves Chemistry【并查集】
- codeforces 722C. Destroying Array(并查集||set)
- CodeForces - 731C Socks(并查集)(贪心)
- CodeForces - 156D:Clues(矩阵树定理&并查集)
- Codeforces 731C Socks(并查集)
- CodeForces - 698B Fix a Tree(并查集)
- 【codeforces 691 D】【并查集 或者 dfs】aps in Permutation【给一个1到N的排列,M个操作,每次可以交换X Y位置上的数字,求可以得到的最大字典序的数列】
- Codeforces 651E Table Compression【并查集】
- CodeForces 722C Destroying Array(并查集和我奇怪的二叉树)
- Codeforces 25D-Roads not only in Berland(并查集)
- CodeForces 755C PolandBall and Forest (并查集)
- 【Codeforces 755 C PolandBall and Forest】+ 并查集
- 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
- codeforces 455C 并查集
- 【并查集分块】Codeforces 475D CGCDSSQ
- Codeforces 722C Destroying Array【逆序(离线)思维+并查集】
- CodeForces 217 A.Ice Skating(并查集)
- CodeForces - 731C Socks(并查集)(贪心)
- CodeForces - 698B Fix a Tree(并查集)
- Codeforces 278C Learning Languages【并查集】水题