【HDU - 5418】Victor and World(tsp旅行商问题,状压dp,floyd最短路,图论)

题干:

After trying hard for many years, Victor has finally received a pilot license. To have a celebration, he intends to buy himself an airplane and fly around the world. There are nn countries on the earth, which are numbered from 11 to nn. They are connected by mm undirected flights, detailedly the ii-th flight connects the uiui-th and the vivi-th country, and it will cost Victor's airplane wiwi L fuel if Victor flies through it. And it is possible for him to fly to every country from the first country. 

Victor now is at the country whose number is 11, he wants to know the minimal amount of fuel for him to visit every country at least once and finally return to the first country.

Input

The first line of the input contains an integer TT, denoting the number of test cases. 
In every test case, there are two integers nn and mm in the first line, denoting the number of the countries and the number of the flights. 

Then there are mm lines, each line contains three integers uiui, vivi and wiwi, describing a flight. 

1≤T≤201≤T≤20. 

1≤n≤161≤n≤16. 

1≤m≤1000001≤m≤100000. 

1≤wi≤1001≤wi≤100. 

1≤ui,vi≤n1≤ui,vi≤n.

Output

Your program should print TT lines : the ii-th of these should contain a single integer, denoting the minimal amount of fuel for Victor to finish the travel.

Sample Input

1
3 2
1 2 2
1 3 3

Sample Output

10

题目大意:

有n个城市,在n个城市之间有m条双向路,每条路有一个距离,现在问从1号城市出发,去游览其它的2到n号城市最后回到1号城市的最短路径(题目数据保证1可以直接或间接到达其他城市)。(n<=16)

解题报告:

因为每个点可以走多次所以不是哈密顿回路,这一个特性也就决定了我们可以用floyd求最短路。

dp[sta][v]代表走过状态为sta并且当前站在v这个城市的最小距离。最后加一个回到原点的距离就行了。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int n,m;
int head[MAX],tot;
int dis[22][22];
int dp[1<<18][18];
bool ok[22];
struct Edge {
	int fr,to,ne;
	int w;
} e[MAX];
void add(int u,int v,int w) {
	e[++tot].fr = u;
	e[tot].to = v;
	e[tot].w = w;
	e[tot].ne = head[u];
	head[u] = tot;
}
void floyd() {
	for(int k = 0; k<n; k++) {
		for(int i = 0; i<n; i++) {
			for(int j = 0; j<n; j++) {
				dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
			}
		}
	}
}
int tsp() {
	int up = 1<<n;
	dp[1][0] = 0; 
	for(int sta = 0; sta < up; sta++) {
		memset(ok,0,sizeof ok);
		for(int i = 0; i<n; i++) {
			if((1<<i) & sta) ok[i] = 1;
		}
		for(int u = 0; u<n; u++) {			
			//可以if(dp==-1)continue  也可以先初始化成0x3f3f3f3f??? 
			for(int v = 0; v<n; v++) {
				if(ok[v]) continue;
				dp[sta|(1<<v)][v] = min(dp[sta|(1<<v)][v],dp[sta][u] + dis[u][v]);
			}
		}
	}
	int ans = 0x3f3f3f3f;
	for(int i = 0; i<n; i++) {
		ans = min(ans,dp[up-1][i] + dis[i][0]);
	}
	return ans;
}
int main()
{
	int t;
	cin>>t;
	while(t--) {
		scanf("%d%d",&n,&m);
		//init 
		tot=0;
		memset(dis,0x3f,sizeof dis);
		memset(dp,0x3f,sizeof dp);
		for(int i = 0; i<n; i++) head[i] = -1,dis[i][i] = 0;
		for(int u,v,w,i = 1; i<=m; i++) {
			scanf("%d%d%d",&u,&v,&w);
			u--,v--;
			add(u,v,w);add(v,u,w);
			if(w < dis[u][v]) dis[u][v] = dis[v][u] = w;
		}
		floyd();
		cout << tsp() << endl;
	}
	return 0 ;
}

 

全部评论

相关推荐

01-16 21:34
武汉大学 Java
点赞 评论 收藏
分享
01-14 10:23
已编辑
湖南师范大学 计调
太久没更新,前几天看到一条评论,说“牛客就是当年那群做题区毕业了开始找工作还收不住那股味”的群体。字里行间透着居高临下的评判,不是,他该不会以为自己很幽默?很犀利吧?作为在牛客混了不算短日子的用户,我感到的不只是被冒犯,更是一种深刻的悲哀——这种以“松弛感”为名,对另一种生存策略的轻蔑,颇有一种自己考不上大学早早出来混社会,嘲笑考上大学的人是书呆子,然后大言不惭地说:死读书有什么用,人脉和资源才是硬道理。我不知道说这个话的人,手头究竟握着多少真正管用的人脉与资源,也不知道他这么傲慢地说出“那股味”的时候,是站在哪一个巨人的肩膀上,才能如此“松弛从容”地俯视众生,还能品评出别人身上“没收住”的余...
淬月星辉:这种评论把正常的努力扭曲成卷😂,说白了就是自己不努力,看着身边努力的人一个个都事业有成了,自己的心里开始不平衡了,就发这种酸言酸语。牛客可以说是我用过那么多平台里社区氛围最好的论坛了,用了大半年了,基本上没见过有人吵架的,都是在互帮互助提建议,帮忙看简历的,帮忙选offer的,帮忙指点学习路线的,分享工作经验和趣事的,我觉得这才是互联网该有的样子。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务