cf 542E - Playing on Graph
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的更多相关文章
- Codeforces 542E Playing on Graph 其他
原文链接https://www.cnblogs.com/zhouzhendong/p/CF542E.html 题目传送门 - CF542E 题目传送门 - 51Nod1481 题意 有一幅无向图,它有 ...
- Codeforces.542E.Playing on Graph(二分图)
题目链接 \(Description\) 给出一个n个点m条边的无向图. 你每次需要选择两个没有边相连的点,将它们合并为一个新点,直到这张图变成了一条链. 最大化这条链的长度,或输出无解. n< ...
- 【Codeforces542E】Playing on Graph [Bfs][Dfs]
Playing on Graph Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample Input 5 4 ...
- Codeforces542E Playing on Graph 思维+DFS+BFS
解法参考https://www.cnblogs.com/BearChild/p/7683114.html这位大佬的,这位大佬讲得很好了. 这道题还是有一定的思维的. 直接贴代码: #include&l ...
- Codeforces刷题计划
Codeforces刷题计划 已完成:-- / -- [Codeforces370E]370E - Summer Reading:构造:(给定某些数,在空白处填数,要求不下降,并且相邻差值<=1 ...
- CF Playing with Paper
Playing with Paper time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 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 ...
- CF 724 G. Xor-matic Number of the Graph
G. Xor-matic Number of the Graph 链接 题意: 给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s, ...
- cf 251 B Playing with Permutations 暴力 分类讨论
题链;http://codeforces.com/problemset/problem/251/B B. Playing with Permutations time limit per test 2 ...
随机推荐
- 第三篇:彻底解决ssh.invoke_shell() 返回的中文问题
接上一篇,前两篇解决中文的问题主要是在字符集上做的手脚,即将中文转成英文,但是有一种情况我们都来不及做转换,即登录时服务器直接返回了中文内容: 此时程序报了如下错误,其实还是字符集问题: 为此:我们可 ...
- 汇编 if else 例子
.text .global _start _start: mov r1,#1 mov r2,#2 cmp r1, r2 bgt branch1 add r3,r1,r2 b end branc ...
- 利用Django提供的ModelForm增删改数据
上一篇我们写了Django基于类如何增删改数据的方法,方法虽然简单,但新手可能对其原理不是很清楚,那么我们这次就用Django提供的ModelForm方法来实现增删改数据,这是一种基于现有模型的增删改 ...
- python各种操作列表的方法及案例
一.循环的使用方法 names = ["张真","刘德华","哈林","谢霆锋","张柏芝"] fo ...
- Gender Equality in the Workplace【职场上的性别平等】
Gender Equality in the Workplace A new batch of young women - members of the so-called Millennial ge ...
- 关于前后端日期处理 开发注意事项 jquery.tmpl()函数的使用
1当后端将日期传到前段的时候 我们通常会需要将日期转为制定格式 除了平常我们使用的前段插件将日期转好 spring @datetimeFormat 注解 这些形式外 我们还可以在实体里通过get方法进 ...
- IE下Date.parse出现NaN有关问题解决
IE不支持"2000-01-01"这种格式的,但是谷歌浏览器支持,改成"2000/01/01"就可以了. 下面的方法两种浏览器就就都支持了 Date.parse ...
- linux环境搭建系列之tomcat安装步骤
前提: Linux centOS 64位 JDK 1.7 安装包从官网上下载 安装Tomcat之前要先安装JDK. 我的JDK是1.7版本的,所以Tomcat版本也选了7的 1.新建目录tomcat ...
- seajs引入jquery
seajs 2.2.1在config文件中preload一次jquery,就可以在整个项目中使用jquery.如下: seajs.on('exec', function(module) { if (m ...
- 启用hyper后无法打开vmware
十万火急,想办法先让虚拟机能够打开,毕竟经常用. 网上看了无数教程都是让在控制面板中关闭hyper-v,然而并没有用. 找了好久说是不能那样关闭,得用指令.管理员运行powershell,输入下列指令 ...