题解 P5921 【[POI1999]原始生物】
题面转化:给定一张图,设添加最少
欧拉路径是指经过图中每一条边的路径。
如果两个图,它们之间没有任何公共边,我们就把它们分成两个子图。
于是我们把给定的图分成
定义
则
连接一条
也就是每次总能找到两个点
而一旦让右边
所以得到
最后温馨提醒这题 n 数据范围是假的
#include <cstring>
#include <iostream>
#include <set>
using namespace std;
#define rg register
#define il inline
#define MX (1000 + 44)
int d[MX] ,fa[MX] ,size[MX] ,occ[MX] ,s[MX];
void init(){
for(int i = 0 ; i < MX ; ++i)
fa[i] = i ,size[i] = 1;
}
int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
void link(int u ,int v){
u = find(u) ,v = find(v);
if(u == v) return;
if(size[u] < size[v]) swap(u ,v);
fa[v] = u ,size[u] += size[v];
}
struct edge{
int u ,v;
bool operator <(const edge& b)const{
return u == b.u ? v < b.v : u < b.u;
}
};
set<edge> e;
int main(){
init();
int n ,del = 0; cin >> n;
for(int i = 1 ,u ,v ; i <= n ; ++i){
cin >> u >> v;
if(e.find((edge){u ,v}) != e.end()){
++del;
continue;
}
e.insert((edge){u ,v});
d[u]++ ,d[v]--;
occ[u] |= occ[v] |= 1;
link(u ,v);
}
for(int i = 1 ; i < MX ; ++i)
if(occ[i]) s[find(i)] += abs(d[i]);
int cnt = 0;
for(int i = 1 ; i < MX ; ++i){
if(occ[i] && find(i) == i){
cnt += max(0 ,(s[i] - 2) / 2);
cnt++;
}
}
cout << n + 1 + cnt - 1 - del << endl;
return 0;
}