P5304 [GXOIGZOI2019]旅行者 最短路+位运算优化

it2023-11-10  66

题意:

给定一张 n n n个点, m m m条有向边的图,标记其中 k k k个点,求这 k k k个点之间的两两最短路的最小值

范围&性质: 1 ≤ k , n ≤ 1 0 5 , 1 ≤ m ≤ 5 × 1 0 5 1\le k, n\le 10^5,1\le m\le 5\times 10^5 1k,n105,1m5×105

分析:

暴力

暴力将关键点分成 A , B A,B A,B两个集合,超级源向 A A A集合每一个点连一条边权为0的边, B B B集合每一个点向超级汇连一条边权为 0 0 0的边,然后从超级源向超级汇跑最短路

正解

我们发现暴力枚举的复杂度不太对,然后我们考虑优化,我们发现正解对应的 s t , e d st,ed st,ed他们的编号必定存在一位不一样,那么我们就枚举二进制位,将这位按照0和1划分成两个集合跑最短路,复杂度 O ( n l o g n 2 ) O(nlog^2_n) O(nlogn2)

代码:

#include<bits/stdc++.h> #define mk(x,y) make_pair(x,y) using namespace std; namespace zzc { const int maxn = 1e5+5; const int maxm = 5e5+5; int head[maxn],key[maxn],ghead[maxn]; long long dis[maxn]; int n,cnt=0,t,st,ed,gcnt,m,k; bool vis[maxn]; struct edge { int to,nxt,val; }e[maxm+maxn]; void add(int u,int v,int w) { e[++cnt].to=v; e[cnt].val=w; e[cnt].nxt=head[u]; head[u]=cnt; } void addedge(int u,int v,int w) { e[++gcnt].to=v; e[gcnt].val=w; e[gcnt].nxt=ghead[u]; ghead[u]=gcnt; } long long dijkstra() { memset(dis,0x3f,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[st]=0; priority_queue<pair<long long,int> > q; q.push(mk(0,st)); while(!q.empty()) { int u=q.top().second;q.pop(); if(vis[u]) continue; vis[u]=true; for(int i=ghead[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]>dis[u]+e[i].val) { dis[v]=dis[u]+e[i].val; q.push(mk(-dis[v],v)); } } } return dis[ed]; } void work() { int a,b,c; scanf("%d",&t); while(t--) { cnt=0; memset(head,0,sizeof(head)); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); } for(int i=1;i<=k;i++) scanf("%d",&key[i]); long long ans=LLONG_MAX; st=n+1;ed=n+2; for(int i=0;(1<<i)<=n;i++) { memcpy(ghead,head,sizeof(head)); gcnt=cnt; for(int j=1;j<=k;j++) { if(j&(1<<i)) { addedge(st,key[j],0); } else { addedge(key[j],ed,0); } } ans=min(ans,dijkstra()); memcpy(ghead,head,sizeof(head)); gcnt=cnt; for(int j=1;j<=k;j++) { if(j&(1<<i)) { addedge(key[j],ed,0); } else { addedge(st,key[j],0); } } ans=min(ans,dijkstra()); } printf("%lld\n",ans); } } } int main() { zzc::work(); return 0; }
最新回复(0)