且未

博客园 首页 新随笔 联系 订阅 管理

题目

这道题,最开始我想用最小生成树(无向)来解决的,然后发现好像写不出来。

看了博客后发现,这道题用并查集来做。

需要涉及到俩个问题:

一、判断成环的时候,只要判断输入边的两个点。有一个共同的父节点,那么这两个点就成环。

二、判断连通的时候,只要判断根节点数为1。或者说:顶点个数+1 = 边的条数

所以我们用了一个edgenum存边的条数,vnum来存顶点数

#include<stdio.h>
#include<iostream>
using namespace std;
bool circle; //判断是否有环
const int Max = 100002;
int par[Max];
bool visit[Max];//在Max个点中,判断是否访问过这个点,由此记录一共有多少个顶点
int edgenum,vnum;
void init()
{
    for(int i=1;i<Max;i++)
    {
        par[i]=i,visit[i]=false;
    }
    circle = false;
    edgenum = vnum = 0;
}
int find (int x)
{
    if(par[x]==x)
    {
        return x;
    }
    else{
        return par[x]=find(par[x]);
    }
}
void unite (int x,int y)
{
    if(x==y) circle = true;
    x=find(x);
    y=find(y);
    if(x!=y) {
        par[x]=y;
        edgenum++;
    }else circle = true;
}

int main()
{
    int a ,b;
    while(true)
    {
        init();
        scanf("%d%d",&a,&b);
        if(a==0&&b==0){
            printf("Yes\n");
            continue;
        }
        if(a==-1&&b==-1) break;
        visit[a] = true;
        visit[b] = true;
        unite(a ,b);
        while(true){
            scanf("%d%d",&a,&b);
            if(a==0 && b==0) break;
            visit[a] = true;
            visit[b]= true;
            unite(a,b);
        }
        for(int i=1;i<Max; i++)
            if(visit[i]) vnum++;
        if(!circle && edgenum+1 == vnum)
            printf("Yes\n");
        else
            printf("No\n");
    }

    return 0;
}


posted on 2017-11-11 21:27  阿聊  阅读(119)  评论(0)    收藏  举报