环和链的判断

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\n");
            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\n");
        else printf("NO\n");
    }
    
    return 0;
}
View Code

第二种做法:

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

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

#include"iostream"
#include"cstdio"
#include"stack"
#include"cstring"
#include"algorithm"
using namespace std;
const int N=10005;
 
int n[2],m[2],cnt_line[2],cnt_cir[2],cnt_line_node[2][N],cnt_cir_node[2][N];
int LOW[N],DFN[N],instack[N],index_s,indegree[2][N];
struct Edge{
    int v,next;
}edge[2][2*N];
int tot[2],head[2][N];
void add(int k,int a,int b){
    edge[k][tot[k]].v=b;edge[k][tot[k]].next=head[k][a];head[k][a]=tot[k]++;
    edge[k][tot[k]].v=a;edge[k][tot[k]].next=head[k][b];head[k][b]=tot[k]++;
}
 
void build_map(int k)
{
    int a,b;
    tot[k]=0;
    memset(head[k],-1,sizeof(head[k]));
    memset(indegree[k],0,sizeof(indegree[k]));
    scanf("%d%d",&n[k],&m[k]);
    while(m[k]--)
    {
        scanf("%d%d",&a,&b);
        add(k,a,b);
        //printf("%d %d \n", a, b);
        indegree[k][a]++;
        indegree[k][b]++;
    }
}
 
stack<int>st;
void Tarjan(int k,int s)
{
    int j,v;
    st.push(s);
    instack[s]=1;
    DFN[s]=LOW[s]=++index_s;
    for(j=head[k][s];j!=-1;j=edge[k][j].next)
    {
        v=edge[k][j].v;
        if(instack[v])    LOW[s]=LOW[s]>DFN[v]?DFN[v]:LOW[s];
        else if(DFN[v]==-1)
        {
            Tarjan(k,v);
            LOW[s]=LOW[s]>LOW[v]?LOW[v]:LOW[s];
        }
    }
    if(LOW[s]==DFN[s])
    {
        int cnt_node=0;
        int cnt_degree=0;
        do
        {
            j=st.top();
            st.pop();
            instack[j] = 0;
            cnt_node++;
            cnt_degree+=indegree[k][j];
        }while(j!=s);
    //    printf("---%d %d \n", cnt_node*2, cnt_degree);
        if(cnt_node*2==cnt_degree)
            cnt_cir_node[k][cnt_cir[k]++]=cnt_node;
        else
            cnt_line_node[k][cnt_line[k]++]=cnt_node;
    }
}
void solve(int k)
{
    int i;
    cnt_line[k]=cnt_cir[k]=0;
    index_s=0;
    memset(LOW,-1,sizeof(LOW));
    memset(DFN,-1,sizeof(DFN));
    memset(instack,0,sizeof(instack));
    for(i=1;i<=n[k];i++)    if(LOW[i]==-1)    Tarjan(k,i);
}
int main()
{
//    freopen("E:\\input.txt", "r", stdin);
    int T,Case;
    int i;
    int ans;
    cin>>T;
    for(Case=1;Case<=T;Case++)
    {
        build_map(0);
        build_map(1);
        solve(0);
        solve(1);
//        printf("%d %d \n", cnt_cir[0], cnt_line[0]);
//        printf("%d %d \n", cnt_cir[1], cnt_line[1]);
        ans=0;
        if(cnt_line[0]!=cnt_line[1] || cnt_cir[0]!=cnt_cir[1])    ans=1;
        if(ans)    {printf("Case #%d: NO\n",Case);continue;}
 
        sort(cnt_line_node[0],cnt_line_node[0]+cnt_line[0]);
        sort(cnt_line_node[1],cnt_line_node[1]+cnt_line[1]);
        for(i=0;i<cnt_line[0];i++)    if(cnt_line_node[0][i]!=cnt_line_node[1][i])    {ans=1;break;}
        if(ans)    {printf("Case #%d: NO\n",Case);continue;}
 
        sort(cnt_cir_node[0],cnt_cir_node[0]+cnt_cir[0]);
        sort(cnt_cir_node[1],cnt_cir_node[1]+cnt_cir[1]);
        for(i=0;i<cnt_cir[0];i++)    if(cnt_cir_node[0][i]!=cnt_cir_node[1][i])    {ans=1;break;}
        if(ans)    printf("Case #%d: NO\n",Case);
        else    printf("Case #%d: YES\n",Case);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/cgjh/p/9571788.html