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