题解 P5921 【[POI1999]原始生物】
【题意】
给定若干条边
【分析】
记点
图构成若干联通块,每个联通块,都要有分成几种情况讨论。
联通块本身有欧拉路径
在这个联通块上不用加边。
存在欧拉回路
等价于对于任意点
不存在欧拉回路
等价于存在两个点,
即
联通块本身无欧拉路径
记
每加一条边,
要让
综上,联通块内的总代价为
还要加上原来的边与连接不同联通块的边。
【算法】
欧拉路径
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5,maxm=1e6+5;
int n,m;
int in[maxn],out[maxn];
int d[maxn];
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++;
}
#define getchar gc
int read(){
int ret=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int ans;
map<int,bool> hsh;
struct data{
int x,y;
}a[maxm];
int fa[maxn];
int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void merge(int x,int y){
int fx=getfa(x),fy=getfa(y);
if(fx==fy) return;
fa[fx]=fy;
d[fy]+=d[fx];
}
int tot,del;
bool vis[maxn];
int main(){
freopen("P5921.in","r",stdin);
freopen("P5921.out","w",stdout);
m=read();
for(int i=1;i<=m;i++){
int x=read(),y=read();
if(hsh[x*maxn+y]){del++;continue;}
hsh[x*maxn+y]=1;
a[++tot]=(data){x,y};
in[x]++,out[y]++;
n=max(n,max(x,y));
vis[x]=vis[y]=1;
}
for(int i=1;i<=n;i++) fa[i]=i,d[i]=abs(in[i]-out[i]);
for(int i=1;i<=tot;i++) merge(a[i].x,a[i].y);
for(int i=1;i<=n;i++) if(vis[i]&&getfa(i)==i) ans+=1+max(0,d[i]-2>>1);
printf("%d\n",m+ans-del);
return 0;
}