UVA-12118 Inspector's Dilemma (欧拉回路)

题目大意:一个有v个顶点的完全图,找一条经过m条指定边的最短路径。

题目分析:当每条边仅经过一次时,路径最短。给出的边可能构成若干棵树。在一棵树中,奇点个数总为偶数,若一棵树的奇点个数为0,则这棵树可以构成欧拉回路,若不为0,则必有走不到的边(每条边仅经过一次,下同)。在一棵树中,设奇点个数为n,则走不到的边数为(n-2)/2 (n-2为除去起点和终点的奇点个数),这意味着,还需要走额外的(n-2)/2条边才能将这(n-2)/2条指定的但走不到的边走完。并且,这(n-2)/2条走不到的边是不共点的,这意味着,一棵树还是多棵树是无关紧要的。但是,如果有的树中奇点个数恰为0,没有走不到的边,此时这棵树成了孤立的了,要注意这种情况。

代码如下:

# include<iostream>
# include<cstdio>
# include<set>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;

struct Edge
{
    int to,nxt;
};
Edge e[500000];
int n,m,t,head[1005],vis[1005],cnt,du[1005],num;
set<int>s;

void add(int u,int v)
{
    e[cnt].to=v;
    e[cnt].nxt=head[u];
    head[u]=cnt++;
}

void dfs(int u)
{
    num+=(du[u]&1);
    for(int i=head[u];i!=-1;i=e[i].nxt){
        int v=e[i].to;
        if(!vis[v]){
            vis[v]=1;
            dfs(v);
        }
    }
}

int main()
{
    int a,b,cas=0;
    while(scanf("%d%d%d",&n,&m,&t)&&(n+m+t))
    {
        cnt=0;
        s.clear();
        memset(head,-1,sizeof(head));
        memset(du,0,sizeof(du));
        for(int i=0;i<m;++i)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
            s.insert(a);
            s.insert(b);
            ++du[a],++du[b];
        }

        num=0;
        memset(vis,0,sizeof(vis));
        for(set<int>::iterator it=s.begin();it!=s.end();++it){
            if(!vis[*it]){
                int temp=num;
                vis[*it]=1;
                dfs(*it);
                if(temp+2>num)///注意树中奇点个数为0的情况
                    num=temp+2;
            }
        }
        printf("Case %d: %d
",++cas,(max(0,(num-2)/2)+m)*t);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/4864181.html