题解
- 首先,我们可以发现,对于一个三元环是不可以合并的,因为合并只能选两个没有直接相连的点
- 对于一个长度大于3的奇环,最后合并一定也会合并出一个三元环
- 那这个图,就是一个二分图
- 先将二分图中的全部联通分量和每个点属于哪个联通分量求出来
- 这个可以用dfs实现
- 对于每一个连通分量都构造了一条链
- 而对于任意两条链
- 显然可以通过一 次合并操作将它们并成一条,长度为它们的长度之和
- 因此,答案就是所有连通块的直径之和
- 可以用bfs实现
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #include <cmath>
5 using namespace std;
6 struct edge { int to,from; }e[100005*2];
7 int n,m,cnt,tot,bz[1005],ans[1005],last[1005],state[1005][2],visit[1005],head,tail,mx;
8 bool boo;
9 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=last[x]; last[x]=cnt; }
10 int abs(int x) { return x<0?-x:x; }
11 void dfs(int x,int k)
12 {
13 if (boo==1) return;
14 bz[x]=k;
15 for (int i=last[x];i;i=e[i].from)
16 {
17 if (boo==1) return;
18 if (bz[e[i].to]==k)
19 {
20 boo=1;
21 return;
22 }
23 if (bz[e[i].to]==-k) continue;
24 dfs(e[i].to,-k);
25 }
26 }
27 int bfs(int x)
28 {
29 memset(visit,0,sizeof(visit));
30 memset(state,0,sizeof(state));
31 head=0; tail=1; state[1][1]=x; visit[x]=1;
32 int r=0;
33 while (head<tail)
34 {
35 head++;
36 int u=state[head][1];
37 r=max(r,state[head][2]);
38 for (int i=last[u];i;i=e[i].from)
39 if (visit[e[i].to]==0)
40 {
41 visit[e[i].to]=1;
42 tail++;
43 state[tail][1]=e[i].to; state[tail][2]=state[head][2]+1;
44 }
45 }
46 return r;
47 }
48 int main()
49 {
50 freopen("merge.in","r",stdin);
51 freopen("merge.out","w",stdout);
52 scanf("%d%d",&n,&m);
53 for (int i=1;i<=m;i++)
54 {
55 int u,v;
56 scanf("%d%d",&u,&v);
57 insert(u,v); insert(v,u);
58 }
59 for (int i=1;i<=n;i++)
60 {
61 if (!bz[i]) dfs(i,++tot);
62 if (boo)
63 {
64 printf("-1
");
65 return 0;
66 }
67 }
68 for (int i=1;i<=n;i++) ans[abs(bz[i])]=max(ans[abs(bz[i])],bfs(i));
69 for (int i=1;i<=tot;i++) mx+=ans[i];
70 printf("%d",mx);
71 return 0;
72 }