使用并查集,套用基本模板即可,详细见注释。(注意第一次就输入 0 0 也要输出 Yes)
#include <iostream>
using namespace std;
const int MAXN = 100005;
int father[MAXN]; //父结点
int vis[MAXN]; //访问情况
bool flag; //是否满足要求
//构建并查集
void makeSet(int n)
{
for (int i = 1; i <= n; i++)
father[i] = i;
}
//查找x所在子树的根结点
int find(int x)
{
if (x != father[x])
father[x] = find(father[x]);
return father[x];
}
//合并x所在的子树和y所在的子树
void unionSet(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
father[fx] = fy;
else //x和y已经处于同一棵子树,又通过其他路径再次查找到二者
flag = false;
}
int main()
{
memset(vis, 0, sizeof(vis));
makeSet(MAXN - 1);
flag = true;
int total = 0; //最小生成树的数量
int u, v;
while (cin >> u >> v)
{
if (u == -1 && v == -1)
break;
else if (u != 0 && v != 0) //输入路径
{
vis[u] = vis[v] = 1;
unionSet(u, v);
}
else
{
if (flag == true) //图内无环
{
for (int i = 1; i < MAXN; i++)
{
if (vis[i] == 1 && i == father[i])
++total;
}
//整个图为连通图,或者第一次就输入 0 0
if (total == 1 || total == 0)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
else
cout << "No" << endl;
memset(vis, 0, sizeof(vis));
makeSet(MAXN - 1);
flag = true;
total = 0;
}
}
return 0;
}
继续加油。