[dfs][bfs] Jzoj P5806 简单的操作

Description

从前有个包含n个点,m条边,无自环和重边的无向图。
对于两个没有直接连边的点u;v,你可以将它们合并。具体来说,你可以删除u;v及所有以它们作为端点的边,然后加入一个新点x,将它与所有在原图中与u或v有直接连边的点连边。
你需要判断是否能通过若干次合并操作使得原图成为一条链,如果能,你还需要求出这条链的最大长度

Input

从文件merge.in中读入数据。
第一行两个正整数n;m,表示图的点数和边数。
接下来m行,每行两个正整数u;v,表示u和v之间有一条无向边

Output

输出到文件merge.out中。
如果能通过若干次合并操作使得原图成为一条链,输出链的最大长度,否则输出-1

Sample Input

【样例1输入】
5 4
1 2
2 3
3 4
3 5
【样例2输入】
4 6
1 2
2 3
1 3
3 4
2 4
1 4

 

Sample Output

【样例1输出】
3
【样例2输出】
-1
 

Data Constraint

对于30%的数据,
对于70%的数据,
对于100%的数据,

题解

  • 首先,我们可以发现,对于一个三元环是不可以合并的,因为合并只能选两个没有直接相连的点
  • 对于一个长度大于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\n");
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 }

原文地址:https://www.cnblogs.com/Comfortable/p/9464258.html

时间: 2024-10-09 08:35:47

[dfs][bfs] Jzoj P5806 简单的操作的相关文章

【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)

[题目链接:NYOJ-58] 经典的搜索问题,想必这题用广搜的会比较多,所以我首先使的也是广搜,但其实深搜同样也是可以的. 不考虑剪枝的话,两种方法实践消耗相同,但是深搜相比广搜内存低一点. 我想,因为广搜需要的就是队列,所以相比递归队列更耗内存? 当然DFS并不像上图所说,需要用栈,而是运用递归即可. BFS: 因为BFS是要一个接一个的遍历,所以用到了结构体,来保存坐标和当前所走步数 1.每走一步,通过定义的结构体,从队列中提取a(即上一步的坐标.步数(步数每次累加)) 2.在a的基础上进行

【dfs/bfs+set+快速幂】swjtuOJ 2094

[dfs/bfs+set+快速幂]swjtuOJ 2094 [注:交大的看到这篇文章要学会自己写,不要为了比赛而比赛!~] 题目大意 问题一:主人公去度假,问经过a^b天后是星期几(简单题) 问题二:一个天平,n个重物,每个物体的重量wi已知,问能称出的所有重量有多少种? 问题二要注意到天平两侧都可以放重物,每一个重物的权值都可以赋值为w,0,-w,相当于三分,我们知道二分可以用二进制位运算进行枚举,例如:枚举所有子集 int j,k,top=0; int t = 1 << n; for(in

Dearboy&#39;s Puzzle (poj 2308 搜索 dfs+bfs)

Language: Default Dearboy's Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1202   Accepted: 208 Description Dearboy is a game lover. Recently, he loves playing the game Lian Lian Kan. This game is played on a board with N*M grids

FZU1205/SDUT1157_小鼠迷宫问题(DFS+BFS)

解题报告 http://blog.csdn.net/juncoder/article/details/38146041 题目传送门 题意 求最短路和最短路的路数. 思路: BFS+DFS,先求出最短路.在DFS搜等于最短路的条数. 不加优化SDUTOJ过了,数据就是水. 确定了最短路的长度,加上奇偶剪枝FOJ也过了. #include <queue> #include <cmath> #include <cstdio> #include <cstring>

使用jxl操作之一: 实现对Excel简单读写操作

项目目录树 对象类UserObject UserObject.java package com.dlab.jxl; public class UserObject { private String userName; private String age; private String address; public String getUserName() { return userName; } public void setUserName(String userName) { this.

poj3083——dfs+bfs综合题

POJ 3083   dfs+bfs+模拟 Children of the Candy Corn Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10564   Accepted: 4539 Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through

android 简单文件操作

1.布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orient

POJ 3083:Children of the Candy Corn(DFS+BFS)

Children of the Candy Corn Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9311 Accepted: 4039 Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombies, ch

Java 实现Excel的简单读取操作

JAVA实现Excel表单的简单读取操作 实现Excel表单的简单读取操作,首先要导入相关的jar包: 如图所示: 此处贴上代码: public static List<List<String>> readExcel(String path){ List<List<String>> list=new ArrayList<List<String>>(); try { Workbook wb; InputStream is=null; t