正题
P5304
题目大意
给你一个有向图以及k个关键点,问你关键点之间最短路距离的最小值
解题思路
考虑两个不同点二进制下必定有一位不同
枚举每一位,把该位为1的作为起点跑最短路,然后对于每个为0的点计算答案,反过来同理
时间复杂度 O(Tnlog2n)O(Tn\ log^2n)O(Tn log2n)
code
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100100
#define mp make_pair
#define fs first
#define sn second
using namespace std;
int T,n,m,k,x,y,z,tot,v[N],h[N],p[N];
ll ans,b[N];
priority_queue<pair<ll,int> >d;
struct rec
{int to,nx,l;
}e[N*5];
void addl(int x,int y,int z)
{e[++tot].to=y;e[tot].nx=h[x];e[tot].l=z;h[x]=tot;return;
}
void dij()
{while(!d.empty()){int x=d.top().sn;d.pop();if(p[x])continue;p[x]=1;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(b[x]+e[i].l<b[y]){b[y]=b[x]+e[i].l;d.push(mp(-b[y],y));}}}return;
}
void solve()
{memset(h,0,sizeof(h));tot=0;ans=1e18;scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;++i){scanf("%d%d%d",&x,&y,&z);addl(x,y,z); }for(int i=1;i<=k;++i)scanf("%d",&v[i]);for(int i=1;i<=k;i<<=1){for(int j=1;j<=n;++j)b[j]=1e18,p[j]=0;for(int j=1;j<=k;++j)if(j&i){b[v[j]]=0;d.push(mp(0,v[j]));}dij();for(int j=1;j<=k;++j)if(~j&i)ans=min(ans,b[v[j]]);for(int j=1;j<=n;++j)b[j]=1e18,p[j]=0;for(int j=1;j<=k;++j)if(~j&i){b[v[j]]=0;d.push(mp(0,v[j]));}dij();for(int j=1;j<=k;++j)if(j&i)ans=min(ans,b[v[j]]);}printf("%lld\n",ans);
}
int main()
{scanf("%d",&T);while(T--)solve();return 0;
}