使用并查集比较方便,每次引入一条边都合并两棵子树,否则就是有回路,满足题目要求有
两点:
1,没有回路
2,所有点都连通,这一点一开始被忽略了
使用并查集并且检查定点数目-1和边数目是不是相同
另外也可根据 图的生成树 使用拓扑排序加上dfs算连通分支
不过遇到的最大问题是输入0 0的测试用例时得输出Yes
当有两层终结输入时一定得小心,0 0输入是个特别情况
原来的循环框架不能识别输入结束,没有输出结果
#include <iostream>
#include <string>
#include <queue>
#include <set>
using namespace std;
int fa[100001];
struct node
{
int from;
int to;
};
int getFa(int n)//这一过程把追溯路径上所有结点直接挂在根上了,降低了高度快捷,甚至可以转化为单层,反正只需要他们共父节点的信息
{
if(fa[n]==n)return n;
fa[n]=getFa(fa[n]);
return fa[n];
}
bool merge(int m,int n)//fa[i]只是其父亲,不是树根
{
if(getFa(m)==getFa(n))return false;
else fa[getFa(n)]=m;
return true;
}
int main()
{
int a,b;
int tag;
queue<node> Q;
set<int> Vnode_num;
node temp;
int count;//记录边数
while(cin>>a>>b&&(a!=-1||b!=-1))
{
if(a==0&&b==0){cout<<"Yes"<<endl;continue;}
tag=1;count=1;
memset(fa,-1,sizeof(fa));
Vnode_num.clear();
temp.from=a;
temp.to=b;
fa[a]=a,fa[b]=b;//先编号存在的等点设置孤立集合
Q.push(temp);
Vnode_num.insert(a);
Vnode_num.insert(b);
while(cin>>a>>b&&(a!=0||b!=0))
{
count++;
temp.from=a;
temp.to=b;
fa[a]=a,fa[b]=b;
Q.push(temp);
Vnode_num.insert(a);
Vnode_num.insert(b);
}
while(!Q.empty())
{
temp=Q.front();
if(!merge(temp.from,temp.to))tag=0;
Q.pop();
}
/*if(!intersect())tag=0;*/
if(Vnode_num.size()!=count+1)tag=0;
if(tag)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}