CodeForces 21 D Traveling Graph

来源:互联网 发布:java软件开发培训机构 编辑:程序博客网 时间:2024/05/27 20:50

Description

You are given undirected weighted graph. Find the length of the shortest cycle which starts from the vertex 1 and passes throught all the edges at least once. Graph may contain multiply edges between a pair of vertices and loops (edges from the vertex to itself).

Input

The first line of the input contains two integers n and m (1 ≤ n ≤ 15, 0 ≤ m ≤ 2000), n is the amount of vertices, and m is the amount of edges. Following m lines contain edges as a triples x, y, w (1 ≤ x, y ≤ n, 1 ≤ w ≤ 10000), x, y are edge endpoints, and wis the edge length.

Output

Output minimal cycle length or -1 if it doesn't exists.

Sample Input

Input
3 31 2 12 3 13 1 1
Output
3
Input
3 21 2 32 3 4
Output
14
要求是每条边至少走一遍的最小花费,先转变为一个欧拉回路问题,即在奇数度的节点上加边使其变为偶数,所有点都为偶数度即有欧拉回路,然后是加边操作,先用floyd预处理出最短路即可。需要注意判断是否可以走遍所有边。
#include<map>#include<cmath>#include<queue>#include<stack>#include<vector>#include<cstdio>#include<bitset>#include<cstring>#include<iostream>#include<algorithm>#include<functional>using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int maxn = 20;int T, n, m, ans, x, y, z;int dis[maxn][maxn], cnt[maxn], fa[maxn];int a[maxn], tot, vis[maxn];int get(int x){return x == fa[x] ? x : fa[x] = get(fa[x]);}int dfs(){for (int i = 0; i < tot; i++){if (vis[i]) continue;int ans = INF;for (int j = i + 1; j < tot; j++){if (vis[j]) continue;vis[i] = vis[j] = 1;ans = min(ans, dis[a[i]][a[j]] + dfs());vis[i] = vis[j] = 0;}return ans;}return 0;}int main(){while (~scanf("%d%d", &n, &m)){ans = 0;for (int i = 1; i <= n; i++){cnt[i] = 0;fa[i] = i;for (int j = 1; j <= n; j++) dis[i][j] = INF;}int flag1 = 0, flag2 = 0;for (int i = 1; i <= m; i++){scanf("%d%d%d", &x, &y, &z);ans += z;if (++cnt[x] == 1) flag2++;if (++cnt[y] == 1) flag2++;int fx = get(x), fy = get(y);if (fx != fy) { fa[fx] = fy; flag1++; }dis[x][y] = min(dis[x][y], z);dis[y][x] = min(dis[y][x], z);}if (n == 1 || m == 0) { printf("%d\n", ans); continue; }if (flag1 + 1 != flag2 || cnt[1] == 0) { printf("-1\n"); continue; }for (int k = 1; k <= n; k++){for (int i = 1; i <= n; i++){if (k == i || dis[i][k] == INF) continue;for (int j = 1; j <= n; j++){if (j == i || j == k) continue;if (dis[k][j] == INF) continue;if (dis[i][j] > dis[i][k] + dis[k][j]){dis[i][j] = dis[i][k] + dis[k][j];}}}}tot = 0;for (int i = 1; i <= n; i++){if (cnt[i] & 1){vis[tot] = 0;a[tot++] = i;}}printf("%d\n", ans + dfs());}return 0;}


0 0