2935: [Poi1999]原始生物

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 150  Solved: 71
[Submit][Status][Discuss]

Description

原始生物的遗传密码是一个自然数的序列K=(a,...,a)。原始生物的特征是指在遗传密码中连续出现的数对(l,r),即存在自然数i使得l=a且r=a。在原始生物的遗传密码中不存在(p,p)形式的特征。
求解任务:
请设计一个程序:
       ·读入一系列的特征。
       ·计算包含这些特征的最短的遗传密码。
        ·将结果输出

Input

 第一行是一个整数n ,表示特征的总数。在接下来的n行里,每行都是一对由空格分隔的自然数l 和r ,1 <= l,r <= 1000。数对(l, r)是原始生物的特征之一。输入文件中的特征不会有重复。

Output

唯一一行应该包含一个整数,等于包含了PIE.IN中所有特征的遗传密码的最小长度。

Sample Input

12
2 3
3 9
9 6
8 5
5 7
7 6
4 5
5 1
1 4
4 2
2 8
8 6

Sample Output

15

注:
PIE.IN中的所有特征都包含在以下遗传密码中:
(8, 5, 1, 4, 2, 3, 9, 6, 4, 5, 7, 6, 2, 8, 6)

HINT

思路:如果是个欧拉回路,一笔画的最少用边数就是边+0,点就是边+1;否则,最少的边数=边+奇数点/2-1,点就是边+奇数点/2;

所以最后答案=边数+欧拉回路数+度数为奇数/2;

(非欧拉回路的一笔画最小边数=边+奇数点/2-1,是因为我们可以把奇数点两两配对,然后求一个欧拉回路,最后随便删去一条边。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int d[maxn],vis[maxn],fa[maxn],sum[maxn],ans,A,B;
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int main()
{
int N,x,y; scanf("%d",&N);
rep(i,,) fa[i]=i;
rep(i,,N) {
scanf("%d%d",&x,&y);
d[x]++; d[y]--; vis[x]=vis[y]=;
fa[find(x)]=find(y);
}
rep(i,,) {
if(vis[i]){
int f=find(i);
sum[f]+=d[i]>=?d[i]:-d[i];
}
}
rep(i,,){
if(vis[i]&&find(i)==i){
if(sum[i]==) A++;
else B+=sum[i];
}
}
printf("%d\n",N+A+B/);
return ;
}
05-01 02:08