您的位置:首页 > 其它

最短的旅程

2016-01-01 18:11 381 查看
在Byteland有n个城市(编号从1到n),它们之间通过双向的道路相连。Byteland的国王并不大方,所以,那里只有n -1条道路,但是,它们的连接方式使得从任意城市都可以走到其他的任何城市。

一天,starhder到了编号为k的城市。他计划从城市k开始,游遍城市m1,m2,m3,……,mj(不一定要按这个顺序旅游),其中j个城市都是不同的,并且也与k不同。Starhder—— 就像每一个旅行家一样,携带的钱总是有限的,所以,他要以最短的路程旅行完所有的城市(从城市k开始)。 于是,他请你帮助计算一下,旅游完上述的城市最短需要多少路程。

输入参数

第一行输入两个整数,即上文中的n和k,以一个空格隔开。下面的n-1行每行描述一条路,每行输入3个整数ai,bi,di,相邻两个数用一个空格隔开(1<= ai,bi<= n,1<= di<= 1000),ai和bi是用道路直接相连的城市编号,di是这条道路的长度。 第n + 1行输入一个整数j,是starhder要旅游的城市数(1<=
j <= n - 1),接下来一行包含j个不同的整数,即m1,m2,……,mj,每两个相邻的整数用一个空格隔开,表示starhder想要去的城市。(1<= mt<=n,mt
不等于k)。

输出参数

输出只有一行,包含一个整数:starhder旅游的最短路程。

样例输入

4 2

1 2 1

4 2 2

2 3 3

2

1 3

样例输出

5

思路:题目中说n个节点总共有n-1条路,所以是一个棵树。先用Floyd求出各节点之间的最短路径,然后将不用去的节点去掉,之后就可以只用剩下的节点求出所要去的最短路径。我用的是暴力搜索,复杂度有点高。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define M 1050
#define inf 0xfffffff
int map[M][M],n,k,city;
bool go[M];          //go[i]表示去没去过城市i
int ans;

void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
map[i][j]=map[j][i]=inf;
go[i]=1;                      //初始化都是去过的,然后输入想去哪些城市,把他们变成没去过
}
}
void floyd()                     //先求出各城市之间的最短路径
{
for(int t=1;t<=n;t++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=min(map[i][j],map[i][t]+map[t][j]);
}
void dfs(int st,int num,int sum)                    //用已知最短路径的图搜索求出最小的路程
{
if(num==city)
{
ans=min(ans,sum);
return;
}
for(int j=1;j<=n;j++)
{
if(!go[j])
{
go[j]=1;
dfs(j,num+1,sum+map[st][j]);
go[j]=0;                          //每个路径不能互相影响,所以不能忘记要复制回来
}
}
}
int main()
{
int s,e,d;
while(~scanf("%d%d",&n,&k))
{
init();
ans=inf;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&s,&e,&d);
map[s][e]=map[e][s]=d;
}
floyd();
scanf("%d",&city);
for(int i=0;i<city;i++)
{
scanf("%d",&s);
go[s]=0;
}
/*        for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",map[i][j]);
printf("\n");
}*/
dfs(k,0,0);
printf("%d\n",ans);
}
return 0;
}
/*
6 2
1 2 1
1 3 1
2 4 2
3 5 2
5 6 2
3
3 4 5
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: