Hand in Hand 【HDU - 3926】【带权并查集】

题目链接


  很好的一道题,关于同构图,一开始没理解,而且他给的数据也很坑,我开始以为完全一样的图就是同构图,但是,很显然WA告诉我,你这么想是错的,于是我就去百度了下什么是同构图,原来结构相似的就是同构图,就是一个五角星和一个五边形可以看作是一对同构图。

  然后,我们讲讲解题思路:我们看到这道题,他说的是每个点最多可以连出两条边,那么,最后所得到的图不是链就是环,所以我们对所有的链上的节点,排序后查它们的子节点的个数是否对应相等;对所有的环,排序后查它们的子节点的个数是否也是对应相等,所以就是判断了。那么既然有环、又有链,我们不妨定义个结构体来判断其是否是链或者环。

  最后说一下,我们查子节点当然是用带权并查集的,但是这儿的带权并查集还有些不一样,你得令特定状态的根节点链接到另一个上面,譬如说,把子节点值少的链接到子节点值多的上去,目的就是为了避免少,或者有些值不同而影响最后的结果。


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=10005;
int N, M, n, m, root[maxN];
struct node
{
    int sum, huan;
    node(int a=1, int b=0):sum(a), huan(b) {}
}a1[maxN], a2[maxN];
void init(int x)
{
    for(int i=1; i<=x; i++) root[i]=i;
}
int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); }
bool cmp(node e1, node e2) { return e1.huan==e2.huan?(e1.sum>e2.sum):(e1.huan>e2.huan); }
int main()
{
    int T;  scanf("%d", &T);
    for(int Cas=1; Cas<=T; Cas++)
    {
        scanf("%d%d", &N, &M);
        for(int i=1; ia1[v].sum) swap(u, v);
            if(u!=v)
            {
                root[u]=v;
                a1[v].sum+=a1[u].sum;
                a1[v].huan=0;
            }
            else a1[v].huan=1;
        }
        scanf("%d%d", &n, &m);
        init(n);
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d", &e1, &e2);
            u=fid(e1);  v=fid(e2);
            if(a2[u].sum>a2[v].sum) swap(u, v);
            if(u!=v)
            {
                root[u]=v;
                a2[v].sum+=a2[u].sum;
                a2[v].huan=0;
            }
            else a2[v].huan=1;
        }
        bool flag = true;
        if(N != n) flag=false;
        sort(a1+1, a1+1+N, cmp);
        sort(a2+1, a2+1+n, cmp);
        for(int i=1; i<=N; i++)
        {
            if(a1[i].sum!=a2[i].sum || a1[i].huan!=a2[i].huan || !flag)
            {
                flag = false;
                break;
            }
        }
        printf("Case #%d: ", Cas);
        printf(flag?"YES\n":"NO\n");
    }
    return 0;
}

 

你可能感兴趣的:(图论)