cf 542E - Playing on Graph

题目大意

给定一个\(n\le 1000\)个点的图

求经过一系列收缩操作后能否得到一条链,以及能得到的最长链是多长

收缩操作:

选择两个不直接相连的点,构造一个新点

对于原图中的每一个点,如果它与这两个点中的任意一个有连边

那么它向这个新点连一条边

最后删除选择的两个点,以及所有这两个点的连边

分析

注意到对于一个奇环,无论怎么收缩,都会产生一个新的奇环,最后奇环变成一个三角形,再也缩不了,永远无法变成一条链

只有偶环的图是二分图

对于图中的一个子图,它是二分图,我们就能构造一组解

选择一个点作为起点,从该点出发得到一棵\(bfs\)树

由于是二分图,\(bfs\)树同一层节点之间没有连边

由于是\(bfs\)树,每个点的连边只能在相邻一层的范围内,且必定和上一层节点有连边

那么我们把同一层节点缩在一起,就可以得到一条链

按照这种方法,图的直径就是答案(图的直径为最短路中的最大值

直径时最优解可以用归纳法证明:

对于\(1\)个点的任意图显然成立

假设对于\(n\)个点的任意图成立,那么对于\(n+1\)个点的任意图

如果图中不存在环,那么是一棵树,直径显然是答案

否则,至少进行一次收缩,则答案为缩掉一对点后的直径中最大是多少

缩掉一个点后的直径一定不比原来的直径大

而原来的直径能构造出一组解

连通块间的答案是相加的:

对于图中的所有联通块,每块缩成一条链后,链可以两两合并

做法

先判断是不是二分图

然后每个联通块求一次图的直径

然后所有联通块的答案加起来

图的直径求法是每个点出发跑一次\(bfs\)

solution

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int M=1007;
const int N=1e5+7; inline int ri(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
} int n,m; struct vec{
int g[M],te;
struct edge{
int y,nxt;
edge(int _y=0,int _nxt=0){y=_y,nxt=_nxt;}
}e[N<<1];
vec(){memset(g,0,sizeof g);te=0;}
inline void push(int x,int y){e[++te]=edge(y,g[x]);g[x]=te;}
inline void push2(int x,int y){push(x,y);push(y,x);}
inline int& operator () (int x){return g[x];}
inline edge& operator [] (int x){return e[x];}
}e; int vis[M],ok,ans;
vector<int>pt;
int d[M]; void dfs(int x){
int p,y;
for(p=e(x);p;p=e[p].nxt){
y=e[p].y;
if(!vis[y]){
vis[y]=3-vis[x];//1->2 2->1
dfs(y);
}
else if(vis[y]!=3-vis[x]) ok=0;
}
} bool chk(){
ok=1;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)
if(!vis[i]) vis[i]=1,dfs(i);
return ok;
} int gao(int bg){
static int q[M];
int h=0,t=1,x,p,y,i,mx=0;
for(i=0;i<pt.size();i++) d[pt[i]]=-1;
q[1]=bg;d[bg]=0;
while(h!=t){
x=q[++h];
mx=max(mx,d[x]);
for(p=e(x);p;p=e[p].nxt)
if(d[y=e[p].y]==-1){
d[y]=d[x]+1;
q[++t]=y;
}
}
return mx;
} void getpt(int x){
vis[x]=1; pt.push_back(x);
for(int p=e(x);p;p=e[p].nxt) if(!vis[e[p].y]) getpt(e[p].y);
} int chain(int x){
int i,mx=0; pt.clear();
getpt(x);
for(i=0;i<pt.size();i++) mx=max(mx,gao(pt[i]));
return mx;
} void solve(){
ans=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)
if(!vis[i]) ans+=chain(i);
printf("%d\n",ans);
} int main(){ int i; n=ri(),m=ri(); for(i=1;i<=m;i++) e.push2(ri(),ri()); if(chk()) solve();
else puts("-1"); return 0;
}

cf 542E - Playing on Graph的更多相关文章

  1. Codeforces 542E Playing on Graph 其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF542E.html 题目传送门 - CF542E 题目传送门 - 51Nod1481 题意 有一幅无向图,它有 ...

  2. Codeforces.542E.Playing on Graph(二分图)

    题目链接 \(Description\) 给出一个n个点m条边的无向图. 你每次需要选择两个没有边相连的点,将它们合并为一个新点,直到这张图变成了一条链. 最大化这条链的长度,或输出无解. n< ...

  3. 【Codeforces542E】Playing on Graph [Bfs][Dfs]

    Playing on Graph Time Limit: 20 Sec  Memory Limit: 512 MB Description Input Output Sample Input 5 4 ...

  4. Codeforces542E Playing on Graph 思维+DFS+BFS

    解法参考https://www.cnblogs.com/BearChild/p/7683114.html这位大佬的,这位大佬讲得很好了. 这道题还是有一定的思维的. 直接贴代码: #include&l ...

  5. Codeforces刷题计划

    Codeforces刷题计划 已完成:-- / -- [Codeforces370E]370E - Summer Reading:构造:(给定某些数,在空白处填数,要求不下降,并且相邻差值<=1 ...

  6. CF Playing with Paper

    Playing with Paper time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  7. CF 329C(Graph Reconstruction-随机化求解-random_shuffle(a+1,a+1+n))

    C. Graph Reconstruction time limit per test 3 seconds memory limit per test 256 megabytes input stan ...

  8. CF 724 G. Xor-matic Number of the Graph

    G. Xor-matic Number of the Graph 链接 题意: 给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s, ...

  9. cf 251 B Playing with Permutations 暴力 分类讨论

    题链;http://codeforces.com/problemset/problem/251/B B. Playing with Permutations time limit per test 2 ...

随机推荐

  1. 使用Vue CLI 3快速创建项目

    首先 vue create ant-design-vue-pro 执行命令会显示两个选项,1默认,2自定义 我么选择自定义 选择好自定义的插件回车就等待下安装成功然后进入项目文件夹 cd ant-de ...

  2. NodeJS--exports和module.exports

    继续迁移印象笔记中记录相关笔记,其实工作中遇到的很多问题当时解决了,后期就忘记了,多记录还是很有用的,好记性不如烂笔头嘛,以后要养成好习惯. NodeJS中 require 用来加载代码,而 expo ...

  3. java实现单链表归并算法

    public class LinkMergeSort {static int number=0;public static void main(String[] args) {int[] a = {1 ...

  4. 回数是指从左向右读和从右向左读都是一样的数,例如 12321 , 909 。请利用 filter() 滤掉非回数

    不管在什么地方,什么时候,学习是快速提升自己的能力的一种体现!!!!!!!!!!! 最近一段时间学习了廖雪峰老师学的Python学习资料,给自己的帮助很大,同时也学到的了很多,今天做了一道练习题,对于 ...

  5. (78)zabbix值缓存(value cache)说明

    在zabbix-2.2版本之前,zabbix计算trigger与calculated/aggregate值都是直接通过sql语句查询并处理出来的结果,为了提高这块的性能与效率,zabbix引入了val ...

  6. Python知识点入门笔记——Python文件操作、异常处理及random模块使用

    文件是存储在外部介质的数据集合,通常可以长久保存,前提是介质不易损坏 Python的绝对路径写法: E:\\编程学习资料\\爬取某社区高清无码大图.py E:/编程学习资料/爬取某社区高清无码大图.p ...

  7. 1497: [NOI2006]最大获利(最大权闭合子图)

    1497: [NOI2006]最大获利 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 5503  Solved: 2673 Description 新的技 ...

  8. PyInstaller打包python脚本

    用python写的工具写好了,想打包然后发给测试同事使用,最后选择了PyInstaller,支持Windows.Linux.OS X,支持打包成一个文件夹或单个EXE文件.   我是直接在线安装的,在 ...

  9. Python+Selenium练习篇之6-利用class name定位元素

    有时候,我们在用firepath(不会的请点这里)查看元素的XPath信息,发现没有可以用来定位的id信息,这个时候我们就需要考虑用其他的可用的来定位元素.本文介绍如何通过元素节点中class nam ...

  10. Notadd 2.0 全新 Node.js 版本~ (开发中) [从 PHP 到 node 的踩坑记]

    对于 Notadd 我们本来期望它实现更多... 尽管我们也尝试做了很多努力,但是由于 PHP 本身的局限,以及考虑到开发环境配置的复杂程度,最终使用了折中方案.接下来,我们谈谈整个技术选型历程,也供 ...