Description
原始生物的遗传密码是一个自然数的序列K=(a1,...,an)。原始生物的特征是指在遗传密码中连续出现的数对(l,r),即存在自然数i使得l=ai且r=ai+1。在原始生物的遗传密码中不存在(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)
Solution
将限制建成边,于是题目的意思就变成了对于每一个联通块,找一个路径最短的欧拉回路/欧拉路径
欧拉路径还有最短的说法?!不可能的,所以肯定是定值。最短这个含义是体现在加边上的
考虑一个联通块,如果其本身是存在一个欧拉回路,即奇度数点为0,那么贡献就是边数加一
否则,奇度数点一定是大于0的偶数 \(x\),我们要加一些边使得图存在欧拉路径,还要让加的边最少,所以就是找 \(x-2\) 个点,两两连边,使图存在欧拉路径,这样的贡献就是加了边后的边数
最后依次考虑每个联通块就好了
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=1000+10;
int n,in[MAXN],out[MAXN],lt,ans,euler[MAXN],cnt,e,beg[MAXN],nex[MAXN*MAXN<<1],to[MAXN*MAXN<<1],vis[MAXN],app[MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
}
inline void dfs(int x)
{
vis[x]=1;
chkmin(euler[cnt],in[x]==out[x]?1:0);
for(register int i=beg[x];i;i=nex[i])
if(!vis[to[i]])dfs(to[i]);
}
int main()
{
read(n);
for(register int i=1;i<=n;++i)
{
int u,v;read(u);read(v);app[u]=app[v]=1;
in[v]++;out[u]++;
insert(u,v);insert(v,u);
chkmax(lt,u);chkmax(lt,v);
}
for(register int i=1;i<=lt;++i)
if(!vis[i]&&app[i])euler[++cnt]=1,dfs(i);
for(register int i=1;i<=lt;++i)
if(app[i])ans+=max(in[i],out[i]);
for(register int i=1;i<=cnt;++i)ans+=euler[i];
write(ans,'\n');
return 0;
}