[Solution] JZOJ-5806 简单的操作

题面

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%的数据, n<=10

对于70%的数据, m<=2000

对于100%的数据, n<=1000,m<=1e5


分割线


解题思路

经过手动模拟,可以发现:当这个图中存在奇环的时候必然无解:因为三元环是肯定无解的(脚动模拟,不解释),所有的奇数元环都可以经过变换成为三元环,因此无解。

重点

不存在奇环的图是二分图(定义,自己去搜),因此搜一遍判二分图可以直接搜出无解的情况输出-1并返回

经过脚动模拟可以发现:每个联通块都可以缩成一条链,链长就是任意两点之间最短路的最大值。

我们继续经过脚动模拟可以发现:任意两个联通块之间相连得到的最大链长就是分别的最大链长之和

然后使用BFS搜一下每个联通块里的最短路中的最大值,然后累加就OK了

具体见Code

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 1005
using namespace std;
int n,m;
struct Edge{
int t,nxt;
}edge[maxn*200];
int head[maxn],tot=0;
int fa[maxn];
int rot[maxn];
int len[maxn];
int book[maxn];
queue<int> q;
int gf(int x){return x==fa[x]?x:fa[x]=gf(fa[x]);}
void add(int st,int to){edge[tot].t=to;edge[tot].nxt=head[st];head[st]=tot;tot++;}
int gmax(int a,int b){return a>b?a:b;}
int check(int s){
memset(book,-1,sizeof(book));
while(q.size()) q.pop();
book[s]=1;
q.push(s);
while(!q.empty()){
int ni=q.front();
q.pop();
for(int i=head[ni];i!=-1;i=edge[i].nxt){
int nt=edge[i].t;
if(book[nt]==-1){
book[nt]=1-book[ni];
q.push(nt);continue;
}
else{
if(book[nt]+book[ni]!=1)
return 0;
}
}
}
return 1;
}
int sp(int s){
while(q.size()) q.pop();
memset(book,-1,sizeof(book));
int ans=0;
book[s]=0;
q.push(s);
while(!q.empty()){
int ni=q.front();
q.pop();ans=gmax(ans,book[ni]);
for(int i=head[ni];i!=-1;i=edge[i].nxt){
int nt=edge[i].t;
if(book[nt]==-1){
book[nt]=book[ni]+1;
q.push(nt);
}
}
}
return ans;
}
int solve(int f){
int ans=-1;
for(int i=1;i<=n;i++)
if(gf(i)==f)
ans=gmax(ans,sp(i));
return ans;
}
int main(){
freopen("merge.in","r",stdin);
freopen("merge.out","w",stdout);
memset(head,-1,sizeof(head));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int a,b;scanf("%d %d",&a,&b);
add(a,b);add(b,a);
if(gf(a)!=gf(b))
fa[gf(a)]=gf(b);
}
tot=0;
for(int i=1;i<=n;i++)
if(gf(i)==i){
rot[tot]=i;
tot++;
}
for(int i=0;i<tot;i++)
if(check(rot[i])==0){
printf("-1\n");return 0;
}
int ans=0;
for(int i=0;i<tot;i++)
ans+=solve(rot[i]);
printf("%d\n",ans);
return 0;
}

[Solution] JZOJ-5806 简单的操作的更多相关文章

  1. salesforce 零基础开发入门学习(三)sObject简单介绍以及简单DML操作(SOQL)

    salesforce中对于数据库操作和JAVA等语言对于数据库操作是有一定区别的.salesforce中的数据库使用的是Force.com 平台的数据库,数据表一行数据可以理解成一个sObject变量 ...

  2. 下面介绍一下 Yii2.0 对数据库 查询的一些简单的操作

    下面介绍一下 Yii2.0 对数据库 查询的一些简单的操作 User::find()->all(); 此方法返回所有数据: User::findOne($id); 此方法返回 主键 id=1 的 ...

  3. SequoiaDB 系列之二 :SequoiaDB的简单CRUD操作

    上一篇通过一系列的操作,终于把SequoiaDB的集群部署到单台机器上了. 建议去安装体验一下吧. 在整个环境的部署的体验来看,并没有MongoDB的部署简单,但是比MongoDB的部署要清晰.Mon ...

  4. js实用方法记录-简单cookie操作

    js实用方法记录-简单cookie操作 设置cookie:setCookie(名称,值,保存时间,保存域); 获取cookie:setCookie(名称); 移除cookie:setCookie(名称 ...

  5. ado.net的简单数据库操作(一)

    摘要:接下来的几篇博客将要讲到如何使用ado.net实现简单的数据库操作,包括增删改等内容.首先会介绍基础的数据库操作,然后以一个实例来进行讲解,这个实例会把一个数据表读取到winform上,然后在w ...

  6. selenium--控制浏览器和简单元素操作

    控制浏览器1.driver.maximize_window() #浏览器最大化2.driver.set_windows_size(480*800) #浏览器设置成移动端大小(480*800),参数数字 ...

  7. [solution] JZOJ 5459. 密室

    [solution] JZOJ 5459. 密室 Description 小X 正困在一个密室里,他希望尽快逃出密室. 密室中有$N$ 个房间,初始时,小X 在1 号房间,而出口在N 号房间. 密室的 ...

  8. Solr可视化简单的操作

    Solr可视化简单的操作 启动solr服务器;在浏览器输入Tomcat启动: http://192.168.191.142:8080/solr/#/ Ø  添加core,首先在存放home的文件下创建 ...

  9. SqlServer简单的操作XML以及SQl的 try catch等统一格式

    1:SqlServer简单的操作XML: ALTER PROCEDURE [dbo].[SP_CRM_FranchiseeRecharge_Money] @Create_By VARCHAR(), @ ...

随机推荐

  1. win10环境下Android studio安装教程----亲测可用

    这段时间学习了一下Android的基本开发,发现Google已经停止了对eclipse的支持,并开发了自己的Android开发工具--Android Studio,于是想安装一下Android Stu ...

  2. nodejs模块循环引用讲解

    CommonJS 模块的重要特性是加载时执行,即脚本代码在require的时候,就会全部执行.一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出. 让我 ...

  3. SpringMVC之DispatcherServlet类图

    DispatcherServlet类图 在IntelliJ IDEA 中打开其源码,然后右键查看Diagrams,工具会自动生成其类图. 可是直观的看出,DispatcherServlet本质上是Se ...

  4. py库: flask笔记

    http://flask.pocoo.org/ http://flask.pocoo.org/docs/0.12/api/#api API http://docs.pythontab.com/flas ...

  5. 开源项目初涉(C++自我学习开始)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://i.cnblogs.com/EditPosts.aspx?postid=8428885 临近2018农历新年,我还在上班,哈哈. ...

  6. 1安装Linux

    第二天笔记打卡. 系统安装注意:1.DATE&TIME2.Server with GUI3.分区默认4.网络开启 源代码安装:1.安装难度高2.编译环境复杂3.解决依赖关系 源代码:2.部署编 ...

  7. Sql入门学习——关系范式

    --------关系 --------范式 一.三种关系 1.一对一关系 关系数据库中,第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关. 2.一 ...

  8. Hibernate 再接触 悲观锁和乐观锁

    为什么取1248 二进制 CRUD 移位效率高 在并发和效率选择一个平衡点 一般不会考虑幻读 因为我们不会再一个事务里查询两次,(只能设置为seralizable) 悲观锁和乐观锁的前提是read-u ...

  9. 最新WordConut

    一.代码地址:https://gitee.com/cainiaoY/WordCount 二.项目分析:代码根据实现的功能不同分为两个模块,一个wcFuctiong类,一个wcTest类,其中wcFuc ...

  10. 判断URL是否能被链接

    判断url是否能被正确链接 function checkUrl(url, name) { $.ajax({ url: url, type: "get", dataType : 'j ...