游客 Signup | Login
中文 | En

1739 - 晨跑

小明是个爱锻炼的好孩子,每天早晨他都会去自己家附近的一个公园晨跑。这个公园里有若干个花坛,这些花坛由一些小路连接。一天,小明在跑步的过程中突然想到这样一个问题:
如果自己可以选择从任何一个花坛开始,想跑步经过每一条小路,每条路至少经过一次,最后必须再回到开始时的花坛,那么最短的跑步路程是多长?

Input

输入包含多组测试数据。
每组输入的第一行为2个正整数n和m(n<=15,m<1000),n表示花坛的个数,m表示小路的个数。当n=0时,输入结束。
接下来m行,每行输入3个正整数s,e,l(1<=s,e<=n,1<=l<=5000),表示标号为s和e的花坛由一条小路相连,长度为l。任意两个花坛之间可能会由多条小路相连而且小路的长度也可能会相等。每条小路都是双向可通行的。从任何一条小路通过连接小路的花坛都可以到达其他任何一条小路。

Output

对于每组输入,输出小明满足题目要求要跑的最短路程。

Examples

Input

4 5
1 2 3
2 3 4
3 4 5
1 4 10
1 3 12
0

Output

41

Solution C++

#include <stdio.h>
#include <string.h>

#define inf 1000000000

int n, l, g[16][16], deg[16], odd[16], flag[16];

int dfs() {
	int i, j, t, r = inf;
	for (i = 0; i < l; i++)
		if (!flag[i])
			break;
	if (i == l)
		return 0;
	flag[i] = 1;
	for (j = i + 1; j < l; j++)
		if (!flag[j]) {
			flag[j] = 1;
			t = dfs() + g[odd[i]][odd[j]];
			r = r < t ? r : t;
			flag[j] = 0;
		}
	flag[i] = 0;
	return r;
}

int main() {
	int m, i, j, k, s, e, v, d;
	while (scanf("%d", &n) != EOF, n) {
		scanf("%d", &m);
		for (i = 1; i <= n; i++)
			for (j = 1; j <= n; j++)
				g[i][j] = inf;
		memset(deg, 0, sizeof(deg));
		for (d = i = 0; i < m; i++) {
			scanf("%d%d%d", &s, &e, &v);
			deg[s]++;
			deg[e]++;
			d += v;
			if (v < g[s][e])
				g[s][e] = g[e][s] = v;
		}
		for (k = 1; k <= n; k++)
			for (i = 1; i <= n; i++)
				for (j = 1; j <= n; j++)
					if (g[i][k] + g[k][j] < g[i][j])
						g[i][j] = g[i][k] + g[k][j];
		for (l = 0, i = 1; i <= n; i++)
			if (deg[i] % 2)
				odd[l++] = i;
		memset(flag, 0, sizeof(flag));
		printf("%d\n", d + dfs());
	}
	return 0;
}
Time Limit 1 second
Memory Limit 32 MB
Discuss Stats
上一题 下一题