题目传送门:https://www.luogu.com.cn/problem/P2307
题目思路:
1. 判断是否有环,如果有环,则不符合条件
2. 如果没有环,判断图是否是连通图,
3. 如果不是连通图,则不符合条件,否则符合条件。
总结:
1. 符合条件的情况:无环且为连通图。
2. 不符合条件的情况:有环或者不是连通图。
判断方式:
1. 判断是否存在环使用并查集。2. 判断是不是连通图也使用并查集。
判断是否存在环:
当向并查集中加入边时,如果边的两端点U和V的祖先已经相同,说明存在环。
判断是否为连通图:
如果存在超过2个点,他们的祖先都是自己,则不是连通图。
#include<iostream>
#include<vector>
#include<set>
using namespace std;
const int MAXN = 100005;
struct Edge{
int u,v;
Edge(int u,int v){
this->u = u;
this->v = v;
}
};
vector<Edge> edges;
bool vis[MAXN];
int father[MAXN];
void initFather(int n){
for(int i=0;i<=n;i++){
father[i] = i;
}
}
int findFather(int x){
int z= x;
while(x != father[x]){
x = father[x];
}
int temp;
while(z != father[z]){
temp = z;
z = father[z];
father[temp] = x;
}
return x;
}
bool unionFather(int x,int y){
int fx = findFather(x);
int fy = findFather(y);
if(fx != fy){
father[fy] = fx;
return false;
}
return true;
}
int judge(int n){
initFather(n);
//判断是否有环
for(int i=0;i<edges.size();i++){
Edge edge = edges[i];
if(unionFather(edge.u,edge.v)){
return 0; //存在环
}
}
int flag = 1;
int cnt = 0;
//判断是否连通
for(int i=1;i<=n;i++){
if(vis[i] && father[i] == i){
cnt++;
if(cnt == 2){ //图不连通
flag = 0;
break;
}
}
}
return flag;
}
int main(){
int u,v;
int maxNum = -1;
while(cin>>u>>v){
if(u == -1 && v == -1){
break;
}
if(u == 0 && v ==0 ){
cout<<judge(maxNum)<<endl;
edges.clear();
maxNum = -1;
}else{
maxNum = max(max(u,v),maxNum);
edges.push_back(Edge(u,v));
vis[u] = vis[v] = true;
}
}
return 0;
}