hdu 3926 hands in hands

https://vjudge.net/problem/HDU-3926

题意:
有n个小朋友,他们之间手拉手,但是一只手只能拉一只手或者不拉,现在给出两个图,表示拉手关系,问这两个图是否同构。
思路:
一开始被同构难住了,后来思考发现,每一个联通分量只能是一条链或者一个简单的环,这样就比较好判断了。利用并查集统计每一个连通分量中的点,然后判断类型,判断类型的时候用度数是否为1来判断是否为链,然后将每一个连通分量先根据大小,再根据类型进行排序,最后把两个图进行一个比较即可。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6
  7 int fao[10004],fat[10004],d[10004];
  8 vector<int> g[10004],v[10004];
  9
 10 struct node
 11 {
 12     int ty,sz;
 13 };
 14
 15 node disc1[10004],disc2[10004];
 16
 17 void init1(int n)
 18 {
 19     for (int i = 1;i <= n;i++)
 20     {
 21         fao[i] = i;
 22     }
 23 }
 24
 25 void init2(int n)
 26 {
 27     for (int i = 1;i <= n;i++)
 28         fat[i] = i;
 29 }
 30
 31 int fin1(int x)
 32 {
 33     if (x == fao[x]) return x;
 34     else return fao[x] = fin1(fao[x]);
 35 }
 36
 37 int fin2(int x)
 38 {
 39     if (x == fat[x]) return x;
 40     else return fat[x] = fin2(fat[x]);
 41 }
 42
 43 void unit1(int x,int y)
 44 {
 45     x = fin1(x);
 46     y = fin1(y);
 47
 48     if (x != y) fao[x] = y;
 49 }
 50
 51 void unit2(int x,int y)
 52 {
 53     x = fin2(x);
 54     y = fin2(y);
 55
 56     if (x != y) fat[x] = y;
 57 }
 58
 59 int dfs1(int n)
 60 {
 61     for (int i = 0;i < g[n].size();i++)
 62     {
 63         int t = g[n][i];
 64
 65         if (d[t] == 1) return 0;
 66     }
 67
 68     return 1;
 69 }
 70
 71 int dfs2(int n)
 72 {
 73     for (int i = 0;i < v[n].size();i++)
 74     {
 75         int t = v[n][i];
 76
 77         if (d[t] == 1) return 0;
 78     }
 79
 80     return 1;
 81 }
 82
 83 bool cmp(node aa,node bb)
 84 {
 85     if (aa.sz == bb.sz)
 86         return aa.ty < bb.ty;
 87     return aa.sz < bb.sz;
 88 }
 89
 90 int main()
 91 {
 92     int t;
 93
 94     scanf("%d",&t);
 95
 96     int cas = 0;
 97
 98     while(t--)
 99     {
100         memset(v,0,sizeof(v));
101         memset(g,0,sizeof(g));
102         memset(disc1,0,sizeof(disc1));
103         memset(disc2,0,sizeof(disc2));
104         memset(d,0,sizeof(d));
105
106         int n,m;
107
108         scanf("%d%d",&n,&m);
109
110         init1(n);
111
112         for (int i = 0;i < m;i++)
113         {
114             int x,y;
115
116             scanf("%d%d",&x,&y);
117
118             d[x]++;
119             d[y]++;
120
121             unit1(x,y);
122         }
123
124         for (int i = 1;i <= n;i++)
125         {
126             g[fin1(i)].push_back(i);
127         }
128
129         int cnt1 = 0;
130
131         for (int i = 1;i <= n;i++)
132         {
133             if (g[i].size() != 0)
134             {
135                 disc1[cnt1].sz = g[i].size();
136                 disc1[cnt1].ty = dfs1(i);
137                 cnt1++;
138             }
139         }
140
141         scanf("%d%d",&n,&m);
142
143         init2(n);
144
145         int cnt2 = 0;
146
147         memset(d,0,sizeof(d));
148
149         for (int i = 0;i < m;i++)
150         {
151             int x,y;
152
153             scanf("%d%d",&x,&y);
154
155             d[x]++;d[y]++;
156
157             unit2(x,y);
158         }
159
160         for (int i = 1;i <= n;i++)
161             v[fin2(i)].push_back(i);
162
163         for (int i = 1;i <= n;i++)
164         {
165             if (v[i].size() != 0)
166             {
167                 disc2[cnt2].sz = v[i].size();
168                 disc2[cnt2].ty = dfs2(i);
169                 cnt2++;
170             }
171         }
172
173         sort(disc1,disc1 + cnt1,cmp);
174         sort(disc2,disc2 + cnt2,cmp);
175
176         bool ff = 0;
177
178         if (cnt1 != cnt2) ff = 1;
179
180         for (int i = 0;i < cnt1;i++)
181         {
182             if (disc1[i].sz != disc2[i].sz) ff = 1;
183             if (disc1[i].ty != disc2[i].ty) ff = 1;
184         }
185
186         if (ff) printf("Case #%d: NO\n",++cas);
187         else printf("Case #%d: YES\n",++cas);
188     }
189
190     return 0;
191 }
时间: 2024-10-05 15:46:13

hdu 3926 hands in hands的相关文章

hdu 3926 Hand in Hand 同构图

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926 In order to get rid of Conan, Kaitou KID disguises himself as a teacher in the kindergarten. He knows kids love games and works out a new game called "hand in hand". Initially kids run on the p

HDU 3926 图的同构

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926 题意:给定2个顶点度最大为2的无向图.问你这2个无向图是否同构. 思路: 1.最大度为2.说明这个图可能有多个连通分量,每个连通分量要么是环,要么是链.2.然后遍历每个连通分量,记录该连通分量的结点个数,以及该连通分量是环还是链.3.将第一个图按照结点个数排序(若子结点个数相同,则对链先排序)4.将第二个图按照步骤三排序5.比较排序后,2个图是否每个元素都相等.若相等,则相似. 关于求链通分量

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

[hdu 2102]bfs+注意INF

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的--把INF改成INF+INF就过了. #include<bits/stdc++.h> using namespace std; bool vis[2][15][15]; char s[2][15][15]; const int INF=0x3f3f3f3f; const int fx[]={0,0,1,-1};

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是