bzoj 2935 [Poi1999]原始生物——欧拉回路思路!

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2935

有向图用最小的路径(==总点数最少)覆盖所有边。

完了完了我居然连1999年的题都做不出来了。

TJ:https://blog.csdn.net/u014609452/article/details/53705451

仔细一想,原来就是欧拉回路的连通块自然不用说,原来不是欧拉回路的连通块,我们在走路径的时候不时从一个点跳到另一个点,其实可以看作是给这两个点间连了一条边!

所以手动连一个欧拉回路。这样应该一定是最小的。

因为是欧拉回路,所以有点浪费。因为其实欧拉路就可以了,只是我们不会连成欧拉路罢了。

考虑把自己连的一条边当做路径的开始或结尾,这样就可以不走那条边,从而变成欧拉路。体现在答案上就是少了一个点,点数==删边前边数。

TJ的代码实现这一过程写得太好啦!无耻默写。

所以需要回顾!

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000;
int n,sum,deg[N+5],fa[N+5],ans;
bool tag[N+5],vis[N+5];
int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
int main()
{
    for(int i=1;i<=N;i++)fa[i]=i;
    scanf("%d",&n);int x,y;ans=n;//原边数 
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        vis[x]=1;vis[y]=1;
        deg[x]++;deg[y]--;
        if(find(x)!=find(y))fa[find(x)]=find(y);
    }
    for(int i=1;i<=N;i++)
        if(vis[i]&&deg[i])tag[find(i)]=1;
    for(int i=1;i<=N;i++)
        if(vis[i]&&fa[i]==i&&!tag[i])ans++;//原欧拉回路+1 
    for(int i=1;i<=N;i++)
        sum+=(deg[i]>0?deg[i]:-deg[i]);//补的边 
    ans+=sum/2;
    printf("%d",ans);
    return 0;
}

 

posted on 2018-07-09 09:17  Narh  阅读(258)  评论(0编辑  收藏  举报

导航