题目描述
TRT出国后,想找一个好的位置住下来。而他所在的城市,恰好有N栋建筑(从1~n编号),他会选择这些建筑的某一个居住。而建筑之间,有M条双向路相连。每条道路有一个起始点u,终止点v,以及走过这条道路所需的时间d。所有建筑都可以借助一些道路相互到达。TRT每天会从他的住房出发,按任意顺序拜访他的K个女神(他想怎么走就怎么走),不过由于TRT精力有限,他的女神个数不会超过12个。可他的女神们都比较娇气,希望TRT尽快来看她们(可她们却不会担心TRT的花心。。。)。对于第i个女神,她住在第p[i]栋建筑物,她每等x分钟(从TRT离家的那一时刻开始计算),她的焦急程度(初始为0)就会增加x。TRT当然希望她们高兴越好,而且他也不会让某个女神特别伤心,所以他希望所有女神的焦急程度的最大值越小越好。且他也不希望与任何一个女神住在一起,要不然会被众人黑成傻逼的(虽然他已经被我们黑成傻逼了)。所以他向你求助,帮他找出他应该住的那栋建筑,以及此时所有女神焦急程度最大值。
输入
第一行:三个正整数 N,M,K
第二行: K个正整数 第i个正整数即是 p[i]
第3 ~ M+2行:描述这些道路 对于每一行 三个正整数描述这条道路 u,v,d
输出
包含两行。
第一行是他所住的建筑物的编号(如果有多种选择,请输出编号最小的那一个)。
第二行是所有女神的焦急程度的最大值的最小值。
样例输入
样例输出
提示
样例解释
输入解释: 有6栋,2和5号有女神。有10条路。
输出解释: TRT在3号建筑安家。他每天的行走路线为3-5-3-2,到达5号建筑的时刻是1 ,那位女神的焦急程度是1;到达2号建筑的时间是5,那位女神的焦急程度是5,最大是5。接下来他爱走哪走哪,反正他已经拜访(****)了所有女神。 可以证明其它方法不比这更优。
数据规模与约定
良心出题人保证
对于20%的数据N<=8,M<=15
对于另外20%的数据 K=1
对于60%的数据 K<=5
对于100%的数据
N<=10^4,M<=5*10^4,K<=12,N>K,1<=p[i],u,v<=N,d<=10^4
本题后80%的数据保证随机
【思路】记录每个女神到达其它所有女神的最短路,只要枚举非女神的点为起点,走到第一个女神点,再加上她到其它女神的最短路。ans取最小。
【题解】
【注意】位运算优先级小于关系运算符
【代码】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=10004;
struct data{
int v,nxt,w;
}e[maxn*11];
int n,m,k,p[22],dst[22][maxn],ans,ansu,fst[maxn],cnt=0,f[22][22][maxn],d[22];
bool gdn[maxn],vst[maxn];
queue<int>q;
inline int get(){
char c;while(!isdigit(c=getchar()));
int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
inline void add(int x,int y,int z){e[++cnt].v=y;e[cnt].w=z;e[cnt].nxt=fst[x];fst[x]=cnt;}
inline void spfa(int num,int s){
memset(vst,0,sizeof(vst));
dst[num][s]=0;vst[s]=1;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=fst[x];i;i=e[i].nxt){
int y=e[i].v;
if(dst[num][y]>dst[num][x]+e[i].w){
dst[num][y]=dst[num][x]+e[i].w;
if(!vst[y])q.push(y),vst[y]=1;
}
}
vst[x]=0;
}
}
int main(){
n=get(),m=get(),k=get();
for(int i=1;i<=k;++i)p[i]=get(),gdn[p[i]]=1;
for(int i=1;i<=m;++i){
int x=get(),y=get(),z=get();
add(x,y,z);add(y,x,z);
}
memset(dst,0x1f,sizeof(dst));
for(int i=1;i<=k;++i)spfa(i,p[i]);
memset(f,0x1f,sizeof(f));
memset(d,0x1f,sizeof(d));
ans=d[0];
int fs=1<<k;
for(int i=1;i<=k;++i){
int ts=1<<(i-1);
f[i][i][ts]=0;
for(int s=ts;s<fs;++s)if(s&ts){
for(int j=1;j<=k;++j)if(s&(1<<(j-1))){
for(int t=1;t<=k;++t)if((s&(1<<(t-1)))==0){
f[i][t][s|(1<<(t-1))]=min(f[i][t][s|(1<<(t-1))],f[i][j][s]+dst[j][p[t]]);
}
}
}
for(int j=1;j<=k;++j)d[i]=min(d[i],f[i][j][fs-1]);
}
for(int i=1;i<=n;++i)if(!gdn[i]){
for(int j=1;j<=k;++j)if(d[j]+dst[j][i]<ans)ans=d[j]+dst[j][i],ansu=i;
}
printf("%d %d\n",ansu,ans);
return 0;
}