A.原始生物
一句话题意:给定一个连通块,求其经过所有边的节点数量最少和(不一定是一笔画,可以多笔划)。
于是我们可以统计每个点在路径中出现的次数,累加即可
可以这样想:对于节点i的入度为 i n in in,出度为 o u t out out,则出现次数为 m a x ( i n , o u t ) max(in,out) max(in,out).因为数量少的一类边一定先被遍历完,所以最后还要单独构造 a b s ( i n − o u t ) abs(in-out) abs(in−out)个点。
题目并没有告诉你整个图联通,我们可以推广,分别求出每个连通块的答案,累加即可。
然而,这道题的坑点是要判断连通块是否存在欧拉回路。如果是,则答案必须加一。因为起点最后又被加入了,比实际 i n [ i ] in[i] in[i]大1.
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
void read(int &x) {
int f=1;x=0;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+(c^48);c=getchar();}
x*=f;
}
int n=1000,in[N],out[N],fa[N],sum[N],flag[N],ans;
int m;
bool pos[N];
int find(int x) {
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int main() {
for(int i=1;i<=1000;i++) fa[i]=i,s[i]=1;
read(m);
for(int i=1,x,y;i<=m;i++) {
read(x),read(y);
pos[x]=pos[y]=1;
out[x]++,in[y]++;
int u=find(x),v=find(y);
if(u!=v) {
fa[u]=v;
}
}
for(int i=1;i<=n;i++) {
if(pos[i]) {
sum[find(i)]+=max(in[i],out[i]);
if(in[i]!=out[i]) flag[find(i)]=1;
}
}
for(int i=1;i<=n;i++) {
if(pos[i]&&fa[i]==i) {
ans+=sum[i];
if(!flag[i]) ans++;
}
}
printf("%d",ans);
}