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 3 1 2 1 2 3 1 3 1 1
Output
3
Input
3 2 1 2 3 2 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; }