HDU 3926 Hand in Hand

传送门

图同构问题 Graph Isomorphism

不过这道题中点的最大度是2,所以图的构型中每个连通分量要么是链(或单个点),要么是单环,所以同等大小的连通分量要区分两种,之后挨个对比就行了。
我一直使用的都是并查集的“根记录个数(负值)版本”。
C++的pair已经写好operator<函数了,按照字典序比较。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <utility>
using namespace std;

const int MAXN = 1e4 + 2;
int N, M, T;
int pre[2][MAXN];
int num = 0;
vector<pair<int, int>> v[2];
bool flag[2][MAXN];

void init()
{
    num++;
    memset(pre, -1, sizeof pre);
    memset(flag, 0, sizeof flag);
    for (int i = 0; i < 2; i++) v[i].clear();
}

int f(int x, int id)
{
    int f0 = x, f1 = x;
    for (; pre[id][f0] > 0;) f0 = pre[id][f0];
    for (; pre[id][f1] > 0;)
    {
        int t = f1;
        f1 = pre[id][f1];
        pre[id][t] = f0;
    }
    return f0;
}

void u(int n1, int n2, int id)
{
    int f1 = f(n1, id);
    int f2 = f(n2, id);
    if (f1 != f2)
    {
        if (pre[id][f1] <= pre[id][f2])
        {
            pre[id][f1] += pre[id][f2];
            pre[id][f2] = f1;
        }
        else
        {
            pre[id][f2] += pre[id][f1];
            pre[id][f1] = f2;
        }
        return;
    }
    // 有环,可以立即加入数组
    v[id].push_back(make_pair(-pre[id][f1], 0));
    flag[id][f1] = 1;
}

int main()
{
    int a, b;
    scanf("%d", &T);
    for (; T--;)
    {
        init();
        for (int t = 0; t < 2; t++)
        {
            scanf("%d%d", &N, &M);
            for (int i = 0; i < M; i++)
            {
                scanf("%d%d", &a, &b);
                u(a, b, t);
            }
            for (int i = 1; i <= N; i++)
            {
                if (pre[t][i] < 0 && !flag[t][i])
                    v[t].push_back(make_pair(-pre[t][i], 1));
            }
            sort(v[t].begin(), v[t].end());       // pair自动按照字典序排序 相同个数的连通分量,环都在前面
        }
        if (v[0].size() != v[1].size())
        {
            printf("Case #%d: NO\n", num);
            continue;
        }
        for (int i = 0; i < v[0].size(); i++)
        {
            if (v[0][i] != v[1][i])
            {
                printf("Case #%d: NO\n", num);
                break;
            }
            if (i == v[0].size() - 1) printf("Case #%d: YES\n", num);
        }
    }

    return 0;
}

// 所谓图同构就是边和点的几何构型是否一致,不涉及点编号和边权值
posted @ 2017-04-10 15:52  CrossingOver  阅读(67)  评论(0编辑  收藏  举报