Description
swimming来到杭州旅行,杭州是个美丽的城市,有很多美丽的景点.但让他头痛的是这些景点之间都有很长的距离,swimming决定选择便宜快捷的公交作为交通工具.杭州的公交网也十分复杂,不同的景点之间要转很多次公交才能到达,已知这些公交都只能站点上下车,并且相同的两个站点之间可能会有多班公交车.swimming想让你帮他设计一条旅游线路,花最少的钱旅游完所有的景点,最后回到出发地.
Input
输入有多组案例.
对于每个案例,第一行包含3个数据,公交站点的个数n(1<=n<=10^4),公交线路数量m(1<=m<=10^5),景点数量k(k<15);接下来m行每行包括三个数据si,ei,vi(0<=si,ei < n 1 <=vi <=100)表示有一班往返于站点si和ei之间的交通线路费用为vi;接下来一行包括k个小于n的整数,表示这些站点附近有景点,swimming必须到达这些站点;最后一行包含一个小于n的整数,表示swimming的出发地.
Output
如果swimming能旅游完所有的景点并且最后回到出发地,输出swimming坐公交旅行的最低花费;如果不能,输出”What a pity”(不加引号).对于每个案例,输出占一行.
Sample Input
5 6 2
0 1 3
1 2 2
0 2 1
2 3 2
1 3 3
3 4 4
1 3
0
Sample Output
9
题解
最短路+压缩DP 的模板题
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f
#define MAX_N 10005
#define MAX_C 15
using namespace std;
typedef pair<int,int> P;
struct edge{int to,cost;};
vector<edge> G[MAX_N];
int d[MAX_N];
int V,E;
int dijkstra(int s,int t){
priority_queue<P,vector<P>,greater<P> > que;
que.push(P(0,s));
fill(d,d+V,INF);
d[s]=0;
while(!que.empty()){
P p=que.top();que.pop();
int c=p.first,v=p.second;
// if(v==t) return c;
if(c>d[v]) continue;
for(int i=0;i<G[v].size();i++){
edge &e=G[v][i];
int dist=c+e.cost;
if(d[e.to]>dist){
d[e.to]=dist;
que.push(P(dist,e.to));
}
}
}
return d[t];
}
int mp[MAX_C][MAX_C];
int dp[1<<MAX_C][MAX_C];
int res[MAX_C],N,se;
void slove(){
for(int S=0;S<1<<N;S++) fill(dp[S],dp[S]+N,INF);
dp[(1<<N)-1][0]=0;
for(int S=(1<<N)-2;S>=0;S--)
for(int v=0;v<N;v++)
for(int u=0;u<N;u++)
if(!(S>>u&1))
dp[S][v]=min(dp[S][v],dp[S|1<<u][u]+mp[v][u]);
if(dp[0][0]==INF) puts("What a pity");
else printf("%d\n",dp[0][0]);
}
int main()
{
int x,y,c;
while(scanf("%d%d%d",&V,&E,&N)!=EOF){
for(int i=0;i<E;i++){
scanf("%d%d%d",&x,&y,&c);
G[x].push_back(edge{y,c});
G[y].push_back(edge{x,c});
}
for(int i=0;i<N;i++)
scanf("%d",&res[i]);
scanf("%d",&se);
bool flag=false;
for(int i=0;i<N;i++)
if(res[i]==se){
swap(res[0],res[i]);
flag=true;
break;
}
if(!flag){
swap(res[0],res[N]);
res[0]=se;
N++;
}
// for(int i=0;i<N;i++)
// printf("%d ",res[i]);
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
mp[i][j]=mp[j][i]=dijkstra(res[i],res[j]);
// printf("%d\n",mp[i][j]);
}
mp[i][i]=0;
}
slove();
for(int i=0;i<V;i++)
while(!G[i].empty())
G[i].pop_back();
}
return 0;
}