Cab
题目描述
HJ,LWC,HRQ三个人在外面比赛,比赛前他们想去外面玩,但是三个人相去的地方不一样。他们坐一辆出租车,请问怎么走,把他们三个都送到目的地的路程最短?
输入
第一行是一个整数K(K<=100),表示样例的个数。每个样例的第一行是两个整数V(3≤V≤1,000),E(E≤40,000),分别表示地点数和街道的数目。地点的编号从1到V,他们的起点编号为0。第二行是三个整数,依次表示三个人想去的地点的编号。以后的E行,每行是一条街道的信息,包含三个整数D,S(0≤D,S≤V),C(1≤C≤100),表示地点D和地点S之间里程为C。输入保证所有地点是可达的,所有的路都是唯一,双向的。
输出
每行输出一个样例的结果,为一个整数,即最短路程的里程数。
样例输入
1 4 7 1 2 3 0 1 4 0 2 5 0 3 6 0 4 1 1 4 2 2 4 3 3 4 2
样例输出
12
题意:三个人去不同的地方,求将他们都送到目的地的最短距离
题解:spfa+排列,求出起点与三个点之间的最短路,然后全排列即可
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
#include<set>
#define inf 100000000
using namespace std;
int visit[1005];
int pre[1005];
int des[1005];
int save[4];
int sg[4][4];
int n,m;
struct lmx{
int to;
int next;
int w;
};
lmx lm[80004];
int spfa(int ii,int jj)
{
int i;
int sr=save[ii];
int de=save[jj];
queue<int> q;
memset(visit,0,sizeof(visit));
for(i=0;i<=n;i++) des[i]=inf;
visit[sr]=1;
des[sr]=0;
q.push(sr);
while(!q.empty())
{
int b=q.front();
q.pop();
visit[b]=0;
for(i=pre[b];i!=-1;i=lm[i].next)
{
if(des[lm[i].to]>des[b]+lm[i].w)
{
des[lm[i].to]=des[b]+lm[i].w;
if(visit[lm[i].to]==0)
{
visit[lm[i].to]=1;
q.push(lm[i].to);
}
}
}
}
return des[de];
}
int main()
{
int test,a,b,c,i,x,cnt,sum,ce,j;
char ss[5]="0123";
set<int> s;
scanf("%d",&test);
while(test--)
{
s.clear();
ce=inf;
cnt=0;
scanf("%d %d",&n,&m);
save[0]=0;
for(i=0;i<3;i++)
{
scanf("%d",&x);
s.insert(x);
}
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
save[++cnt]=*it;
}
memset(pre,-1,sizeof(pre));
int pp=0;
for(i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
lm[pp].to=b;
lm[pp].next=pre[a];
lm[pp].w=c;
pre[a]=pp++;
swap(a,b);
lm[pp].to=b;
lm[pp].next=pre[a];
lm[pp].w=c;
pre[a]=pp++;
}
memset(sg,0,sizeof(sg));
for(i=0;i<=cnt;i++)
{
for(j=0;j<=cnt;j++)
{
if(i!=j)
{
sg[i][j]=spfa(i,j);
}
}
}
do{
sum=0;
for(i=0;i<cnt;i++) sum+=sg[ss[i]-'0'][ss[i+1]-'0'];
if(sum<ce) ce=sum;
}while(next_permutation(ss+1,ss+cnt+1));
printf("%d\n",ce);
}
return 0;
}
为了明天所以选择坚定的执着今天。