• 环和链的判断


    Hand in Hand  HDU - 3926 

    给一一副有单环的图 判断是否同构

    我们可以判断环有多少个,链有多少个,同时判断一下每个环的点数和链的点的个数

    第一种做法:

    所以,我们可以直接用并查集来做.

    同时,我们注意到两幅图的人数应该是一样的.

    所以,把并查集修改一下就直接判断了. (如果成环,最后成环的并集会让点的个数加倍.  同时,因为人数是固定的,所以可以直接sort,然后比较)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int fa[10050];
    int id1[10050], id2[10050]; 
    int find(int idx) { return fa[idx] < 0 ? idx : fa[idx] = find(fa[idx]); }
    
    inline void Union(int x, int y) {
        int xf = find(x);
        int yf = find(y);
        if (fa[xf] > fa[yf]) swap(xf, yf);
        fa[xf] = fa[xf] + fa[yf];
        if (xf == yf) return ;  // 注意 放到这个位置的意义,就是为了判环.
        fa[yf] = xf;
    }
    
    int main()
    {
        int t, n, m, i, v, u, cnt1, cnt2;
        scanf("%d", &t);
        for (int cas=1; cas<=t; ++cas) {
            memset(fa, -1, sizeof(fa));    
            scanf("%d%d",&n, &m);
            for (i=1; i<=m; ++i) {
                scanf("%d%d", &u, &v);
                Union(u, v);
            }
            cnt1 = cnt2 = 0;
            for (i=1; i<=n; ++i) 
                if (fa[i]<0) id1[cnt1++] = abs(fa[i]);
            memset(fa, -1, sizeof(fa));    
            scanf("%d%d", &n, &m);
            for (i=1; i<=m; ++i) {
                scanf("%d%d", &u, &v);
                Union(u, v);
            }
            for (i=1; i<=n; ++i) 
                if (fa[i]<0) id2[cnt2++] = abs(fa[i]);
            printf("Case #%d: ", cas);
            if (cnt1 != cnt2) {
                printf("NO
    ");
                continue;
            }
            sort(id1, id1+cnt1);
            sort(id2, id2+cnt2);
            for (i=0; i<cnt1; ++i) 
                if (id1[i] != id2[i]) break;
            if (i==cnt1) printf("YES
    ");
            else printf("NO
    ");
        }
        
        return 0;
    }
    View Code

    第二种做法:

    我们注意到别个点的度数都只有2.所以我们Tarjan可以根据点的个数和度数来判环.

    用Tarjan求连通分量, 同时将每个环和链的点数分别求出.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    struct Edge {
        int lst;
        int to;
    };
    
    class TARJAN {
    public:
        Edge edge[20500];
        int n, m;
        int head[10500]; int qsz;
        
        int  dfn[10500]; 
        int  dfn_num;  
        int  low[10500];     
        
        int inSt[10500];    
        int st[10500]; int top; 
        
        int cir[10500];
        int line[10500];
        int in[10500];
        int cir_cnt, line_cnt;
        
        void init() {
            qsz = 1;
            cir_cnt = line_cnt = 0;
            dfn_num = top = 0;
            memset(head, 0, sizeof(head));
            memset(dfn, 0, sizeof(dfn));
            memset(in, 0, sizeof(in));
        }
        
        inline void add(int u, int v) {
            edge[qsz].lst = head[u];
            edge[qsz].to  = v;
            head[u] = qsz++;    
        }
        
        void build() {
            int i, u, v;
            scanf("%d%d", &n, &m);
            for (i=1; i<=m; ++i) {
                scanf("%d%d", &u, &v);
                add(u, v);
                add(v, u);
                in[u]++;
                in[v]++;
            }
        }
        
        void Tarjan(int u) {
            int v, i;
            dfn[u] = low[u] = ++dfn_num;
            st[++top] = u;    
            inSt[u] = true;     
            for (i=head[u]; i; i=edge[i].lst) {
                v = edge[i].to;        
                if (!dfn[v]) {
                    Tarjan(v);
                    low[u] = min(low[u], low[v]);
                } else if (inSt[v]) {
                    low[u] = min(low[u], dfn[v]);
                }
            }
            if (dfn[u] == low[u]) { 
                int cnt_node = 0;
                int cnt_in   = 0;
                do {
                    inSt[st[top]] = false;
                    cnt_node++;
                    cnt_in += in[st[top]];
                } while (st[top--] != u);
                if (cnt_node*2 == cnt_in) // 这个题度数都只有2  所以如果节点数乘以2等于所有点入度,那么就成环. 
                    cir[cir_cnt++]   = cnt_node;
                else 
                    line[line_cnt++] = cnt_node;
            }
        }
        
        void _get() {
            init();
            build();
            for (int i=1; i<=n; ++i) 
                if (!dfn[i]) 
                    Tarjan(i);
        }
    }t1, t2;
    
    
    
    int main()
    {
        int t, n, m, u, v, i, cas;
        scanf("%d", &t);
        for (cas=1; cas<=t; cas++) {
            t1._get();  t2._get();
    
            printf("Case #%d: ", cas);
            if (t1.cir_cnt!=t2.cir_cnt || t1.line_cnt!=t2.line_cnt) {
                printf("NO
    ");
                continue;
            }
            sort(t1.cir, t1.cir+t1.cir_cnt);
            sort(t2.cir, t2.cir+t2.cir_cnt);
            bool flag = true;
            for (i=0; i<t1.cir_cnt; ++i) {
                if (t1.cir[i] != t2.cir[i]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
            sort(t1.line, t1.line+t1.line_cnt);
            sort(t2.line, t2.line+t2.line_cnt);
                for (i=0; i<t1.line_cnt; ++i) {
                    if (t1.line[i] != t2.line[i]) {
                        flag = false;
                        break;
                    }
                }
            }
    
            if (flag) printf("YES
    ");
            else printf("NO
    ");
        }
        
        
        return 0;
    }
    View Code
  • 相关阅读:
    单点登陆
    【springmvc学习】常用注解总结
    Excel里函数中的万金油,你确定不要点进来看看?
    Maven3在Eclipse上安装插件
    VSCode 云同步扩展设置 Settings Sync 插件
    Ubuntu 18.04 root 使用ssh密钥远程登陆
    [Asp.net] C# 操作Excel的几种方式 优缺点比较
    开源框架Autofac使用入门
    C# .net Ueditor实现图片上传到阿里云OSS 对象存储
    [python]TypeError: string indices must be integers解决方法
  • 原文地址:https://www.cnblogs.com/cgjh/p/9571788.html
Copyright © 2020-2023  润新知