小鑫的城堡

Description

从前有一个国王,他叫小鑫。有一天,他想建一座城堡,于是,设计师给他设计了好多简易图纸,主要是房间的连通的图纸。小鑫希望任意两个房间有且仅有一条路径可以相通。小鑫现在把设计图给你,让你帮忙判断设计图是否符合他的想法。比如下面的例子,第一个是符合条件的,但是,第二个不符合,因为从5到4有两条路径(5-3-4和5-6-4)。 

Input

多组输入,每组第一行包含一个整数m(m < 100000),接下来m行,每行两个整数,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。 

Output

每组数据输出一行,如果该城堡符合小鑫的想法,那么输出"Yes",否则输出"No"。

Sample Input

5
2 5
2 3
1 3
3 6
4 6
6
1 2
1 3
3 4
3 5
5 6
6 4

Sample Output

Yes
No
 
 
 
代码:
(此题挺难,一输入0 0时保证输出Yes。二保证不出现环,也就是每添加新元素时判断两者祖宗是否一样,若一样,合并函数返回值0,不一样,返回1,在后面控制flag。三保证只是一个集合,这一点好难写程序,下面代码中引入了一个t值,增加元素,标记一下,判断是否为新元素,如果增加n个新元素,t就变为t+n,此时如果只有一个集合,那么合并的次数也会为n,在返回值为1的情况下t--,最终t=1。如果有多个集合,t最终大于1。  为什么要这样判断集合,因为元素数不是连续的,不能用传统的找祖宗个数=1来判断,此法很好很妙,利用了键。)
#include <stdio.h>
#include <string.h>


int bin[100001];
int wz[1000001];


int find(int x)
{
    int r = x;
    while (bin[r]!=r)
    {
       r=bin[r];
    }
    int i = x;
    while(bin[i]!=r)
    {   int j;
        j = bin[i];
        bin[i] = r;
        i = j;
    }
    return r;
}
int merge(int x,int y)
{
    int fx,fy;
    fx = find(x);
    fy = find(y);
  if(fx != fy)
   {
       bin[fy] = fx;
         return 1;
   }
   else
    return 0;
}
int main ()
{
    int x,y,flag,i,t,T,j;
    while (~scanf("%d",&T))
    {
        scanf("%d%d",&x,&y);
        memset(wz,0,sizeof(wz));
        memset(bin,0,sizeof(bin));
        for (i = 0;i < 100001;i++)
        {
            bin[i] = i;
        }
        merge(x , y);
       wz[x] = 1;
       wz[y] = 1;
        t = 1;          (进一步解释t:可理解为键,初始连接两个,键为1,同一集合内增加n个新元素,)
        flag = 1;
         for(j = 1;j<=T-1;j++) (无论怎么连,需要n个新键,r个集合需要的新键为n-r+1个)
        {
            scanf("%d%d",&x,&y);


           if (wz[x] == 0)
            {
                t++;
                wz[x] = 1;
            }
            if (wz[y] == 0)
            {
                t++;
                wz[y] = 1;
            }
            int z = merge(x,y);
            if (z == 1)
                t--;
            else
                flag = 0;


        }
        if (flag == 1&&t==1)
            printf ("Yes\n");
        else
            printf ("No\n");
    }
    return 0;
}
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值