zoukankan      html  css  js  c++  java
  • HDU1272_并查集

    题目大意:            让你输入n,m,代表一个迷宫中的两个点,要求这个迷宫中,不能有回路。这是一个无向图,但是其实根据题意来说,最终应该是一棵树。 解题思路:            只要输入的时候一开始判断两个点的父节点是不是相同的,如果相同,那么说明这两个点是连通的,你再加上去,就证明要产生回路啦。所以要排除,,还有,当输入n,m为0时,这时候输出yes,最后再判断下,这个图有没有连通分量就可以了。。。
    #include 
    #include 
    using namespace std; 
    const int MAX=100005;
    int pre[MAX]; 
    int visited[MAX];
    int find(int x) 
    { 
    	int r, j; 
    	r = x; 
    	while(pre[r] != r) 
    	{ 
    		r = pre[r]; 
    	} 
    	while(pre[x] != r) //优化
    	{ 
    		j = pre[x];//从底部,一个一个判断上去,如果有一个父节点不是根节点,那么就将它放在根节点上
    		pre[x] = r; 
    		x = j;
    	} 
    	return r; 
    } 
    //int find(int x)
    //{
    //
    //    int r=x;
    //
    //    while(pre[r]!=r)
    //
    //        r=pre[r];
    //
    //    return r;
    //}
    //void merge(int x,int y)
    //{
    //
    //    int fx,fy;
    //
    //    fx=find(x);
    //
    //    fy=find(y);
    //
    //    if(fx!=fy)
    //
    //        pre[fx]=fy;
    //}
    
    int main(void) 
    {
    	int n, m, f1, f2;
    	while(scanf("%d%d", &n,&m)==2)
    	{
    		memset(visited,0,sizeof(visited));
    		for(int i = 1; i < MAX; i++) 
    			pre[i] = i;
    		if (n == -1 && m == -1 )
    			break;
    		if (n == 0 && m == 0 )
    		{  
    			printf("Yes\n");
    			continue;
    		}
    		f1 = find(n); 
    		f2 = find(m); 
    		pre[f1]=f2;
    		visited[n]=visited[m]=1;
    		int minn=200005,maxn=0,flag=0;
    		if ( n< minn )     minn = n;           //找到输入 的所有数据中最小的和最大的便于减小最后数组遍历时的复杂度 
    			if ( m < minn )     minn = m;
    			if ( n> maxn )     maxn = n;
    			if ( m > maxn )     maxn = m;
    		while(scanf("%d%d", &n,&m)) 
    		{ 
    			if ( n== 0 && m == 0)
    				break;        
    			if ( n< minn )     minn = n;           //找到输入 的所有数据中最小的和最大的便于减小最后数组遍历时的复杂度 
    			if ( m < minn )     minn = m;
    			if ( n> maxn )     maxn = n;
    			if ( m > maxn )     maxn = m;
    
    			visited[n]=visited[m]=1;
    
    			f1 = find(n); 
    			f2 = find(m); 
    
    			if(f1==f2)
    			{
    				flag=1;
    			}
    			else
    			{
    				pre[f1]=f2;
    			}
    		} 
    		if(flag==1)
    			printf ("No\n");
    		if (flag==0)
    		{
    			for (int i = minn; i <= maxn; i++)
    			{
    				if ( visited[i] && pre[i] == i )
    					flag++;
    			}
    			if (flag == 1)
    				printf ("Yes\n");
    			else
    				printf ("No\n");
    		}          
    	} 
    	return 0; 
    }
    
  • 相关阅读:
    wpf button的mouse(leftbutton)down/up,click事件不响应解决办法
    多线程引发OutOfMemoryException
    WINDBUG常用命令
    有关OEP脱壳
    reversing.kr easykeygen 之wp
    reversing.kr easy crack 之write up
    pwnable.kr leg之write up
    pwnable input2 之 write up
    pwnable.kr random 之 write up
    pwnable.kr 之 passcode write up
  • 原文地址:https://www.cnblogs.com/cchun/p/2520177.html
Copyright © 2011-2022 走看看