uva 12118 欧拉路径dfs

我觉得这个例子很难体现,所以自己想了个例子:

uva 12118 欧拉路径dfs_第1张图片
V E T 分别为 8 7 1
如上图
先只看上面5个点 从0-4
我们需要走 0-1 0-3 0-2 0-4 这几条路(从哪一方向都可以走)(也可以重复遍历,因为没说,但我们不选择这么做,后面会有原因),因为要求经过这四条边最短的遍历过程,我们只需要做一条一笔画,保证这四个边在一笔画里就可以实现最短。
先看看我们可以怎么走 0-2-1-0-3-4-0 或者 0-2-0-1-0-3-0-4 不难发现我们前者构造了一条欧拉路径。
我们转变问题:在现有边的基础上加上几条边就可以做成一笔画?

我们可以统计0-4这些点的奇度顶点个数:4个 只要加一条边就会少2个奇度顶点,但由于欧拉图的性质:我们可以有且仅有2个奇度顶点作为起始点和终止点,3-0-1-2-0-4 这就是最优方案。我们只加了一条1-2边
按照上面过程,0-4结点处理完毕

处理5-8

同样四个奇度顶点(这奇度顶点个数一定是偶数个,也是性质哦)我们构造欧拉路径,添加6-7,5作起始点,8做终止点
连接4(上图终止点)和下图的5(下图起始点)就解决了一个完整一笔画问题;

总结:求连通分支数量-1 和每个连通分量构成欧拉路径《加边的个数》 就是构成一笔画需要的总加边数,此题*T 每边有个构造值,就结束了。

#include
#include
#include
const int maxn = 1000 + 10;
using namespace std;
vector<int>G[maxn];


int vis[maxn];

int n;
int dfs(int x){
    vis[x]=1;int cnt=G[x].size()%2;
    for(int i=0;i<G[x].size();i++){
        if(!vis[G[x][i]]){
            cnt+=dfs(G[x][i]);
        }
    }
    return cnt;
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    int v,e,t;
    int a,b;
    int ts=1;
    while(scanf("%d%d%d",&v,&e,&t)!=EOF){for(int i=1;i<=v;i++)G[i].clear();memset(vis,0,sizeof(vis));n=v;
        if(v==e&&e==0)break;
        for(int id=0;id<e;id++){
            scanf("%d%d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        int ans=0;
        for(int i=1;i<=v;i++){
            if(!vis[i]&&G[i].size()>0){
                int c=dfs(i);
                ans+=max(0,(c-2)/2);
                ++ans;
            }
        }
    if(ans>0)ans--;
    printf("Case %d: %d\n",ts++,t*(e+ans));

    }



return 0;}

你可能感兴趣的:(图)