• 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
    ");//!!!特判一下!!!
            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
    ");
                        else
                            printf("No
    ");
                        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
    ");
            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
    ");
                else printf("No
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    今年的第几天?
    特殊乘法
    abc
    求最大最小数
    二叉树遍历
    球的半径和体积
    成绩排序
    OC学习篇之---类的定义
    OC学习篇之---第一个程序HelloWorld
    OC学习篇之---类的初始化方法和点语法的使用
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/6917271.html
Copyright © 2020-2023  润新知