您的位置:首页 > 其它

AtCoder Beginner 073 joisino's travel(多源最短路径Floyd|DFS)

2017-09-09 22:25 639 查看

题目链接

题意

一共有n个点,m个边,现在一个人要去其中的r个地点R1,R2,R3,R4…Rr(不一定按照这个顺序)他可以坐飞机去第一个点,然后坐飞机从最后一个点返回,剩下的点只能走路,让我们求出“经过这r个点的最短路程”

这个题我坑了,刚开始没有想到可以从任意一个点出发。一直以为题意是必须从第一个点出发,所以把dfs()里面的for(int i=1;i<=r;i++)写成了for(int i=2;i<=r;i++),后来想到可以从任意一个路径出发的时候,这里忘了改过去了

/(ㄒoㄒ)/~~自作聪明图省事啊…

解决

跑一遍floyd,求出多源最短路径

枚举起点,深搜即可(由于r<=8,所以深搜的深度并不会很深)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<(b);++i)
const int INF = 0x3f3f3f3f;

bool vis[10];
int ans=INF;
int n,m,r;
int R[10];
int d[205][205];
void dfs(int x,int cur)         //x是地点编号,cur是已经走过的距离
{
bool flag = 1;
for(int i=1;i<=r;i++) if(!vis[R[i]]) flag=0 ;
if(flag&&cur<ans){              //已经经过了所有的r个点
ans=cur;
return;
}

for(int i=1;i<=r;i++){
if(vis[R[i]]) continue;
if(d[x][R[i]]>=INF) continue;
vis[R[i]]=true;
dfs(R[i],cur+d[x][R[i]]);
vis[R[i]]=false;
}
return ;
}

int main()
{
scanf("%d%d%d",&n,&m,&r);
rep(i,1,r+1) scanf("%d",&R[i]);

for(int i=0;i<205;i++) for(int j=0;j<205;j++) {
if(i==j) d[i][j]=0;
else d[i][j]=INF;
}

rep(i,0,m){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
d[u][v]=w;              //bidirectional双向边
d[v][u]=w;
}

for(int k=1;k<=n;k++)       //floyd
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j] = min(d[i][j],d[i][k]+d[k][j]);

memset(vis,0,sizeof(vis));
for(int i=1;i<=r;i++){      //枚举起点
vis[R[i]]=true;
dfs(R[i],0);
vis[R[i]]=false;
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: