Codeforces 542E. Playing on Graph

4 篇文章 0 订阅
3 篇文章 0 订阅

题目
题意:给出一个?个点?条边的无向图。你每次需要选择两个没有边相连的点,将它们合并为一个新点,直到这张图变成了一条链。最大化这条链的长度,或输出无解

Solution

可以发现,奇环->奇环+偶环;偶环->奇环+奇环或偶环+偶环(单独一条边看作偶环)
所以奇环最终一定会变成三元环,而三元环是无解的,所以奇环是无解的,二分图判一下
然后给每个联通块求一遍直径,加起来即为最终答案

Code

#include<bits/stdc++.h>
using namespace std;
const int N=1002;
struct node{
	int to,ne;
}e[N*N];
int n,m,i,x,y,col[N],h[N],num[N],bel[N],cnt,dis[N],tot,ans;
queue<int>q;
bool fl;
inline char gc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
	int x=0,fl=1;char ch=gc();
	for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
	for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
	return x*fl;
}
void add(int x,int y){
	e[++tot]=(node){y,h[x]};
	h[x]=tot;
}
void dfs(int u){
	bel[u]=cnt;
	for (int i=h[u],v;i;i=e[i].ne)
		if (col[v=e[i].to]==-1){
			col[v]=col[u]^1;
			dfs(v);
		}else if (col[v]==col[u]) fl=1;
}
void bfs(int x){
	memset(dis,-1,sizeof(dis));
	q.push(x);dis[x]=0;
	while (!q.empty()){
		int u=q.front();q.pop();
		for (int i=h[u],v;i;i=e[i].ne)
			if (dis[v=e[i].to]==-1){
				dis[v]=dis[u]+1;
				q.push(v);
			}
	}
	int &mx=num[bel[x]];
	for (int i=1;i<=n;i++) mx=max(mx,dis[i]);
}
int main(){
	n=rd();m=rd();
	for (i=1;i<=m;i++) x=rd(),y=rd(),add(x,y),add(y,x);
	memset(col,-1,sizeof(col));
	for (i=1;i<=n && !fl;i++)
		if (col[i]==-1) cnt++,col[i]=0,dfs(i);
	if (fl) return puts("-1"),0;
	for (i=1;i<=n;i++) bfs(i);
	for (i=1;i<=cnt;i++) ans+=num[i];
	printf("%d",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值