• AGC014E Blue and Red Tree


    题意

    There is a tree with (N) vertices numbered (1) through (N). The (i)-th of the (N−1) edges connects vertices (a_i) and (b_i).

    Initially, each edge is painted blue. Takahashi will convert this blue tree into a red tree, by performing the following operation (N−1) times:

    • Select a simple path that consists of only blue edges, and remove one of those edges.
    • Then, span a new red edge between the two endpoints of the selected path.

    His objective is to obtain a tree that has a red edge connecting vertices (c_i) and (d_i), for each (i).

    Determine whether this is achievable.

    分析

    这题可以倒着想,在原图中最后删掉的边,在新图中也一定是以同样的方式出现。

    那么我们可以看成一开始原图中有n个点连通块,每次找一条在原图和新图中都出现的边,把这条边的两个端点缩成一个点,然后继续进行以上操作。

    若还未合并至一点且无法继续合并则不可行。

    用并查集维护连通块,map维护边出现的次数,set维护点的邻接点,用queue维护当前可合并的点对。合并时需要找到第一个不在同一连通块中的可合并点对(因为以前的合并可能让它们属于同一连通块),find一下合并连通块的并查集的根,然后用启发式合并把x的邻接点赋给y,删掉x的一切记录(省空间),最后把出现次数改变成2的边放入queue中。

    代码

    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<list>
    #include<deque>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<complex>
    #pragma GCC optimize ("O0")
    using namespace std;
    template<class T> inline T read(T&x){
        T data=0;
    	int w=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
        while(isdigit(ch))
            data=10*data+ch-'0',ch=getchar();
        return x=data*w;
    }
    typedef long long ll;
    typedef pair<int,int>pii;
    
    const int MAXN=1e5+7;
    
    int n;
    map<ll,int>M;
    queue<pii>Q;
    set<int>l[MAXN];
    int fa[MAXN];
    
    int find(int x)
    {
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    ll getid(int x,int y)
    {
    	if(x>y)
    		swap(x,y);
    	return (ll)x*n+y;
    }
    
    void link(int x,int y)
    {
    	l[x].insert(y);
    	l[y].insert(x);
    	ll v=getid(x,y);
    	++M[v];
    	if(M[v]==2)
    		Q.push(pii(x,y));
    }
    
    int main()
    {
    //  freopen(".in","r",stdin);
    //  freopen(".out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;++i)
    		fa[i]=i;
    	for(int i=1;i<=2*n-2;++i)
    	{
    		int x,y;
    		read(x);read(y);
    		link(x,y);
    	}
    	for(int i=1;i<n;++i)
    	{
    		int x,y;
    		while(1)
    		{
    			if(Q.empty())
    			{
    				printf("NO
    ");
    				return 0;
    			}
    			x=Q.front().first,y=Q.front().second;
    			Q.pop();
    			x=find(x),y=find(y);
    			if(x!=y)
    				break;
    		}
    		if(l[x].size()>l[y].size())
    			swap(x,y);
    		fa[x]=y;
    		M.erase(getid(x,y));
    		l[y].erase(x);
    		for(auto v:l[x])
    		{
    			v=find(v);
    			if(v==y)
    				continue;
    			M.erase(getid(x,v));
    			l[v].erase(x);
    			l[x].erase(v);
    			link(v,y);
    		}
    	}
    	printf("YES
    ");
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    js 中基本数据类型和引用数据类型 ,,,, js中对象和函数的关系
    something
    js 的constructor属性
    js 的prototype 属性和用法,外加__proto__
    js 获取一下url里面的一些内容
    js 终于明白变量提升的概念了
    动态设置小程序的 标题
    Vue axios调用第三方接口跨域解决
    css translate的一些问题 这其实可以用在,不知道div宽高的情况,从而让其上下,左右都居中。
    用css3写一个可以无限旋转的div或者图片
  • 原文地址:https://www.cnblogs.com/autoint/p/9526504.html
Copyright © 2020-2023  润新知