***Victor and World***
Problem Description
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 n countries on the earth, which are numbered from 1 to n. They are connected by m undirected flights, detailedly the i-th flight connects the ui-th and the vi-th country, and it will cost Victor's airplane wi 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 1, 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 T, denoting the number of test cases.
In every test case, there are two integers n and m in the first line, denoting the number of the countries and the number of the flights.
Then there are m lines, each line contains three integers ui, vi and wi, describing a flight.
1≤T≤20.
1≤n≤16.
1≤m≤100000.
1≤wi≤100.
1≤ui,vi≤n.
Output
Your program should print T lines : the i-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
题目大意:经过多年的努力,Victor终于考到了飞行驾照。为了庆祝这件事,他决定给自己买一架飞机然后环游世界。他会驾驶一架飞机沿着规定的航线飞行。在地球上一共有nn个国家,编号从11到nn,各个国家之间通过mm条双向航线连接,第ii条航线连接第u_iu
i
个国家与第v_iv
i
个国家,通过这条航线需要消耗w_iw
i
升油,且从11号国家可以直接或间接到达22到nn中任意一个国家。
Victor一开始位于11号国家,他想知道从11号国家出发,经过各个国家至少一次并最后回到11号国家消耗的总油量的最小值是多少。
解题思路:
Floyd算法和状态dp
上代码:
/*
2015 - 8 - 29 中午
Author: ITAK
今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define INF 1e9+7
const int sizet = (1<<16);
int d[16][16];
int dp[sizet][16];
int n,m;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
{
if(i == j) d[i][j] = 0;
else d[i][j] = INF;
}
int u,v,w;
for(int i=0; i<m; ++i)
{
scanf("%d%d%d",&u,&v,&w);
if(d[u-1][v-1] > w)
{
d[u-1][v-1] = w;
d[v-1][u-1] = w;
}
}
for(int k=0; k<n; k++)
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
for(int i=0; i<sizet; ++i)
for(int j=0; j<n; ++j)
dp[i][j] = INF;
dp[1][0] = 0;
for(int k=1; k<sizet; ++k)
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
dp[k|(1<<i)|(1<<j)][i] = min(dp[k|(1<<i)|(1<<j)][i],d[j][i]+dp[k|(1<<j)][j]);
int minx=INF;
int tt = (1<<n)-1;
for(int i=0; i<n; i++)
if(minx > dp[tt][i]+d[i][0])
minx = dp[tt][i]+d[i][0];
printf("%d\n",minx);
}
return 0;
}