POI代码等式

Poi1999基因片段
  问题描述

有这样一段遗传基因K,它是由一系列的自然数组成:K=a1,a2,a3,a4……am。在该段基因中,连续的两个自然数被称做它的“特征”。

例如对基因段:8, 5, 1, 4, 2, 3

(5,1)就是它的“特征”之一,而(4,3)则不是。

L教授正在研究这样一段长度未知的奇特基因段,并且已经成功地分析出了该基因段的大多数“特征”。

G={V,E}

V={v |存在x使得(v,x)S(x,v)S}

E=S

 

 
 本地图片,请重新上传

现在,他想根据自己当前的研究成果,确定这段基因最少有多长,你能帮助他么?

样例输入:

3

1 2

2 3

3 4

样例输出:

41234

 

分析:

这一看,就是搜索,然后这个时间就瞬间爆炸完成爆炸,所以我们肯盯要想新的方法。

 

我们最近在学并查集啊,你一看这个输入格式,是不是就像给出了n条边,那每个数字不就是几个点,他要你练成一串数字,就是将这些点练成一条带方向的欧拉路

 

关于这个欧拉路的知识啊,这个就是非常重要。

注意这里的欧拉路是要把所有的边走遍,所有的“特征“都要包含进去。

 

样例给的比较水我们再来看一个例子:

3

1 2

2 3

2 1

这时候最少就是12321,长度为5

因为2连着两条边,这时候你又要把所有的边都走遍,所以你必须再添加一条边使得每条边都走到,所以我在这里选择新增一条32的边(新增一条12的边也可以),就能走完原来2所连的2条边。

 

基本的思路就出来了:

通过添加边来构成一条单向的欧拉路,长度就是所有的(原来的边+新增的边)+1

这个+1是细节很重要啊,因为这是边数,而边是连2个点的,所以欧拉路的末尾还会多出一个点,所以长度是所有的边数+1

 

最后就只有一个问题了:如何确定要新增多少条边呢?

 

这里就要用到单向边欧拉路的性质了,

对于这个欧拉路里的每一个点,除了起点和终点的入度和出度之差的绝对值为1,其他点的入度和出度都是相同的。

 

所以在这道题中,要求出新增的边数,我们就计算所有点入度和出度之差的绝对值,因为你添加1条边可一帮助1个点入度加1和另1个点出度加1,所以把所有点入度和出度之差的绝对值加起来的和除以2再减1(因为起点和终点的入度和出度之差的绝对值为1),就是新增的边数。

 

总结:

这道题的精妙之处在于把求这个长度转化为求一个图的欧拉路的长度,但我只想说这跟并查集有基本关系。虽然好像有人强行用并查集方便理解

 

附上AC代码,强迫症患者自行修改格式:

#include<cstdio>

#include<cstdlib>

#define maxn 1000001

 

int n,ans=0;

int jin[maxn],chu[maxn],cha[maxn];

 

void prework()

{

       intx,y;

       scanf("%d",&n);

       for(inti=1;i<=n;i++)

       {

              scanf("%d%d",&x,&y);

              chu[x]++;

              jin[y]++;

       }

}

 

void mainwork()

{

       for(inti=1;i<=n;i++)

              cha[i]=abs(jin[i]-chu[i]),ans+=cha[i];

       ans=ans/2-1;

}

 

void print()

{

       printf("%d",ans+n+1);

}

 

int main()

{

       prework();

       mainwork();

       print();

       return0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值