题目
题目描述
TRT出国后,想找一个好的位置住下来。而他所在的城市,恰好有N栋建筑(从
1
∼
n
1\sim n
1∼n编号),他会选择这些建筑的某一个居住
而建筑之间,有
M
M
M条双向路相连。每条道路有一个起始点
u
u
u,终止点
v
v
v,以及走过这条道路所需的时间
d
d
d
所有建筑都可以借助一些道路相互到达
TRT
每天会从他的住房出发,按任意顺序拜访他的
K
K
K个女神(他想怎么走就怎么走),不过由于TRT
精力(???)有限,他的女神个数不会超过
12
12
12个
可他的女神们都比较娇气,希望TRT
尽快来看她们可她们却不会担心TRT的花心……
对于第
i
i
i个女神,她住在第p[i]栋建筑物,她每等
x
x
x分钟(从TRT
离家的那一时刻开始计算),她的焦急程度(初始为
0
0
0)就会增加
x
x
x
TRT
当然希望她们高兴越好,而且他也不会让某个女神特别伤心,所以他希望所有女神的焦急程度的最大值越小越好
且他也不希望与任何一个女神住在一起,要不然会被众人黑成傻逼的虽然他已经被我们黑成傻逼了
所以他向你求助,帮他找出他应该住的那栋建筑,以及此时所有女神焦急程度最大值
输入格式
第一行:三个正整数
N
,
M
,
K
N,M,K
N,M,K
第二行:
K
K
K个正整数 第
i
i
i个正整数即是
p
i
p_i
pi
第
3
∼
M
+
2
3\sim M+2
3∼M+2行:描述这些道路 对于每一行 三个正整数描述这条道路
u
,
v
,
d
u,v,d
u,v,d
输出格式
一行包含两个数
第一个是他所住的建筑物的编号(如果有多种选择,请输出编号最小的那一个)
第二个是所有女神的焦急程度的最大值的最小值
样例
样例输入
6 10 2
2 5
1 5 2
5 6 3
6 2 4
5 3 1
6 3 2
2 3 3
1 2 4
1 4 3
3 4 5
2 4 2
样例输出
3 5
数据范围与提示
样例解释
TRT
在
3
3
3号建筑安家。他每天的行走路线为
3
→
5
→
3
→
2
3\rightarrow 5\rightarrow 3\rightarrow 2
3→5→3→2
到达
5
5
5号建筑的时刻是
1
1
1,那位女神的焦急程度是
1
1
1
到达
2
2
2号建筑的时间是
5
5
5,那位女神的焦急程度是
5
5
5,最大是
5
5
5
接下来他爱走哪走哪,反正他已经拜访 (∗∗) 了所有女神。 可以证明其它方法不比这更优
数据规模与约定
对于
20
%
20\%
20%的数据
N
⩽
8
,
M
⩽
15
N\leqslant 8,M\leqslant 15
N⩽8,M⩽15
对于另外
20
%
20\%
20%的数据
K
=
1
K=1
K=1
对于
60
%
60\%
60%的数据
K
⩽
5
K\leqslant 5
K⩽5
对于
100
%
100\%
100%的数据
N
⩽
1
0
4
,
M
⩽
5
×
1
0
4
,
K
⩽
12
,
N
>
K
,
1
⩽
p
i
,
u
,
v
⩽
N
,
d
⩽
1
0
4
N\leqslant 10^4,M\leqslant 5\times 10^4,K\leqslant 12,N>K,1\leqslant p_i,u,v\leqslant N,d\leqslant 10^4
N⩽104,M⩽5×104,K⩽12,N>K,1⩽pi,u,v⩽N,d⩽104
本题后
80
%
80\%
80%的数据保证随机
题解
看看这个
k
k
k,它这么小,难道不香吗?
显然是个状压DP
首先跑
k
k
k遍SPFA,把图压缩成只包含女神的住处,边为两两的最短路的图
设
f
i
,
j
,
s
f_{i,j,s}
fi,j,s表示起点为
i
i
i,当前城市为
j
j
j,遍历状态为
s
s
s的最短时间
转移就是直接枚举上一个拜访的女神的房子,最后加上到起点的最近城市的距离就可以了
附上代码:
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
struct ppap
{
int to,nxt,ver;
}e[100010];
queue<int> q;
int n,m,k,tot,h,ans,p[20],w[10010],head[10010],dis[20][10010],v[10010],f[20][20][10010],g[20];
void add(int u,int v,int w)
{
e[++tot].nxt=head[u],head[u]=tot,e[tot].to=v,e[tot].ver=w;
}
void spfa(int k,int x)
{
memset(v,0,sizeof(v)),dis[k][x]=0,v[x]=1,q.push(x);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt) if(dis[k][e[i].to]>dis[k][u]+e[i].ver){
dis[k][e[i].to]=dis[k][u]+e[i].ver;
if(!v[e[i].to]) q.push(e[i].to),v[e[i].to]=1;
}
v[u]=0;
}
}
int main()
{
freopen("godness.in","r",stdin);
freopen("godness.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++) scanf("%d",&p[i]),w[p[i]]=1;
for(int i=1,x,y,z;i<=m;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
memset(dis,0x1f,sizeof(dis)),memset(f,0x1f,sizeof(f)),memset(g,0x1f,sizeof(g)),ans=g[0];
for(int i=1;i<=k;i++) spfa(i,p[i]);
for(int i=1;i<=k;i++){
f[i][i][1<<(i-1)]=0;
for(int s=(1<<(i-1));s<(1<<k);s++) if(s&(1<<(i-1))) for(int j=1;j<=k;j++) if(s&(1<<(j-1)))
for(int t=1;t<=k;t++) if(!(s&(1<<(t-1))))
f[i][t][s|(1<<(t-1))]=min(f[i][t][s|(1<<(t-1))],f[i][j][s]+dis[j][p[t]]);
for(int j=1;j<=k;j++) g[i]=min(g[i],f[i][j][(1<<k)-1]);
}
for(int i=1;i<=n;i++) if(!w[i]) for(int j=1;j<=k;j++) if(g[j]+dis[j][i]<ans) ans=g[j]+dis[j][i],h=i;
printf("%d %d",h,ans);
}