hdu 1272 使用set和并查集

http://acm.hdu.edu.cn/showproblem.php?pid=1272

这道题就是求图是不是连通无环,我觉得其实就是看看图是不是一棵最小生成树。

所以要是图满足条件,就必然有n个节点,n-1条边。但是题目中若只有 0 0一组数据也是可以的!!!!!这里WA了好多回。

所以我首先采用stl里面的set来直接判断:

  

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<set>
#include<cstring>
using namespace std;
const int maxn = 1005;
int n, m;

int main()
{
    set<int> s;
    int x, y;
    int tot = 0;
    while (scanf("%d%d", &x, &y) == 2)
    {
        if (x == -1 && y == -1) break;
        if (x == 0 && y == 0) printf("Yes\n");//!!!特判一下!!!
        else
        {
            tot++, s.insert(x), s.insert(y);//把点加入set,tot计录边的数目
            for (int i = 1;; i++) {
                scanf("%d%d", &x, &y);
                if (x == 0 && y == 0) {
                    if (s.size() == tot + 1)
                        printf("Yes\n");
                    else
                        printf("No\n");
                    s.clear();
                    tot = 0;
                    break;
                }
                s.insert(x), s.insert(y);
                tot++;
            }
        }
    }
    return 0;
}

 

当然,原本的做法是用并查集,效率比set高很多:

 

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<set>
#include<cstring>
using namespace std;
const int maxn=100005;
int n,m;
int f[maxn],flag[maxn];

int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

int Union(int x,int y)
{
    int rx=find(x);
    int ry=find(y);
    if (rx==ry){
        return 0;
    }else{
        f[rx]=ry;
        return 1;
    }
}

int main()
{
    int x,y,t,Flag;
    while(scanf("%d%d",&x,&y)==2)
    {
        memset(flag,0,sizeof(flag));
        for (int i=1;i<=maxn;i++) f[i]=i;
        if (x==-1&&y==-1) break;
        if (x==0&&y==0) printf("Yes\n");
        else
        {
            Union(x,y);
            flag[x]=1,flag[y]=1;//记录点已在图中
            t=1,Flag=1;//开始存在一棵树。没有环。
            while(scanf("%d%d",&x,&y)==2)
            {
                if (x==0&&y==0) break;
                if (flag[x]==0){t++,flag[x]=1;}//x是新节点,树+1
                if (flag[y]==0){t++,flag[y]=1;}//y是新节点,树+1
                if (Union(x,y)==0) Flag=0;//存在回路
                    else t--;//x,y合并,树-1
            }
            if (Flag&&t==1) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

 

posted @ 2017-05-29 08:40  ╰追憶似水年華ぃ╮  阅读(134)  评论(0编辑  收藏  举报