习题 6-14 UVA - 12118 Inspector's Dilemma 检察员的难题 (DFS 构造欧拉通路)

来源:互联网 发布:php 数组key长度限制 编辑:程序博客网 时间:2024/05/17 03:04

期末考试也快结束了,抽个空补个题做做 = =!!

大体题意:

给你一个无向图,任意两个顶点都是双连通的,给你e个 必须走的边,和每个边的权值t,问最少多少权值恰好完全经过这e个必须走的边。

思路:

最短恰好完全走过,那不就是一笔画吗,不就是欧拉通路吗,并且任意两个点都是双连通,肯定能构造出欧拉通路来。

先用vector数组  在建立这张无向图,然后计算出度数是奇数的顶点个数ans,答案就是 ( ans - 2) / 2,减去两头的,并且连接一条边需要消耗两个顶点,这(ans-2)/2就是答案, 最后还要加上e  因为之前算的是 连接多个连通图的边数,e是需要走的边数,两者相加就是最后结果。

但要注意:  ans 可能会是0,这样算出来答案是负数,  比如   1-2   2-3  3-1,这是一个环,并没有奇度顶点,ans是0,但这种情况  你随便选个起点 随便选个终点就好了,所以当ans 小于2 时  直接给他赋值为0就好了。

最后一点说的是就是 用dfs 计算 每一个联通块奇度顶点的个数,没啥好说 的  发现vector数组中 对应的G是奇数,递归加就可以了。

还有一个要注意的。在计算每个联通块奇度顶点个数时,如果小于2,那么应直接赋值为2,还是那个环,  环随便选个起点和终点,奇度顶点个数就是2了。

详细见代码,可能说的有点乱。

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxn = 1000 + 10;int v,t,e;vector<int>g[maxn];int vis[maxn];int cnt;int dfs(int k){    if (vis[k])return 0;    int ans = 0;    vis[k] = 1;    int tmp = (int)g[k].size();    if (tmp % 2 == 1)++ans;    for (int i = 0; i < (int)g[k].size(); ++i){        ans += dfs(g[k][i]);    }    return ans;}int main(){    while(scanf("%d%d%d",&v,&e,&t) == 3 && (v || t || e)){        for (int i = 0; i <= v; ++i){            g[i].clear();        }        memset(vis,0,sizeof vis);        for (int i = 0; i < e; ++i){            int u,v;            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        int ans = 0;        for (int i = 1; i <= v; ++i){            if (!vis[i] && !g[i].empty())                ans += max(dfs(i),2);        }        int rmp = (ans < 2 ? 0 : (ans-2) / 2);        printf("Case %d: %d\n",++cnt,t*(rmp + e));    }    return 0;}



0 0
原创粉丝点击