【LOJ3087】「GXOI / GZOI2019」旅行者
阿新 • • 發佈:2019-04-22
cond spa endif tmp lin long long stdin efi ++i
題意
給定一個 \(n\) 個點 \(m\) 條邊的的有向圖,給出 \(k\) 個關鍵點,求關鍵點兩兩最短路的最小值。
\(n\le 10^5, m\le 5\cdot 10^5\).
Solution
二進制枚舉。對於每一位,將編號當前位為 \(0\) 的點做源點, 當前位為 \(1\) 的點做匯點,然後跑最短路。
復雜度 \(O(n\log ^2 n)\) .
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; namespace io { const int SIZE=(1<<21)+1; char ibuf[SIZE],*iS,*iT,c; int qr; #define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++) inline int gi (){ int x=0; for(c=gc();c<'0'||c>'9';c=gc()); for(;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15); return x; } } using io::gi; const int N=1e5+5,M=5e5+5; typedef long long ll; int head[N],nxt[M],to[M],wei[M],n,m,k,key[N]; #define pr pair<int,int> priority_queue< pr,vector<pr>,greater<pr> > q; ll dis[N]; void addedge(int u, int v, int w, int now) { nxt[now]=head[u], head[u]=now, to[now]=v, wei[now]=w; } int main() { #ifdef lc freopen("a.in","r",stdin); #endif int T=gi(); while(T--) { memset(head,0,sizeof(head)); n=gi(),m=gi(),k=gi(); for(int i=1;i<=m;++i) { int u=gi(),v=gi(),w=gi(); addedge(u,v,w,i); } for(int i=1;i<=k;++i) key[i]=gi(); ll ans=1ll<<60; for(int i=0;i<17;++i) { memset(dis,0x3f,sizeof(dis)); for(int j=1;j<=k;++j) if(key[j]&(1<<i)) { dis[key[j]]=0; q.push(make_pair(0,key[j])); } while(!q.empty()) { ll tmp=q.top().first; int u=q.top().second; q.pop(); if(dis[u]!=tmp)continue; for(int e=head[u];e;e=nxt[e]) if(dis[to[e]]>dis[u]+wei[e]) { dis[to[e]]=dis[u]+wei[e]; q.push(make_pair(dis[to[e]],to[e])); } } for(int j=1;j<=k;++j) if(!(key[j]&(1<<i))) ans=min(ans,dis[key[j]]); } for(int i=0;i<17;++i) { memset(dis,0x3f,sizeof(dis)); for(int j=1;j<=k;++j) if(!(key[j]&(1<<i))) { dis[key[j]]=0; q.push(make_pair(0,key[j])); } while(!q.empty()) { ll tmp=q.top().first; int u=q.top().second; q.pop(); if(dis[u]!=tmp)continue; for(int e=head[u];e;e=nxt[e]) if(dis[to[e]]>dis[u]+wei[e]) { dis[to[e]]=dis[u]+wei[e]; q.push(make_pair(dis[to[e]],to[e])); } } for(int j=1;j<=k;++j) if(key[j]&(1<<i)) ans=min(ans,dis[key[j]]); } printf("%lld\n",ans); } }
【LOJ3087】「GXOI / GZOI2019」旅行者