标签:otto -- log block jks ret src base read
调这个题调了两个月,被自己蠢哭
给一个有向图,一组关键点,求关键点之间的最短的距离
这个题目有两种做法,分别是 $nlogn$ 和 $nlog^2n$ 的
首先说 $nlogn$ 的官方做法,我们考虑多源迪杰斯特拉
正图上从 k 个关键点出发跑 $dijkstra$ ,记某个点离最近的关键点距离为 $dis[0][i]$
反图上也从 k 个关键点出发跑 $dijkstra$ ,距离记为 $dis[1][i]$
枚举正图中的边 $u->v: w$, 用 $dis[0][u]+dis[1][v]+w$ 更新答案
然后就是一种很好打的 $nlognlogk$ 的做法,我们考虑一种思想,二进制分组
对于每一个在集合中的元素,我们进行重新标号,然后对每一位进行$0/1$二进制分组,由于每个元素的编号不一样,所以至少有一位的分组不同,然后一组连 $S$,一组连 $T$,这样跑 $logk$ 组的从 $S$ 到 $T$ 的最短路,去 $min$,即可
#include <bits/stdc++.h> using namespace std; #define re register #define ll long long #define gc getchar() inline int read() { re int x(0),f(1);re char c(gc); while(c>‘9‘||c<‘0‘)f=c==‘-‘?-1:1,c=gc; while(c>=‘0‘&&c<=‘9‘)x=x*10+c-48,c=gc; return f*x; } const int N=5e5+10,M=1e6+10; ll INF=1e15+7; int h[N],n,m,cnt,k,a[N],x[N],y[N],z[N],s,t; struct node {int next,to,w;}e[M<<1]; ll dis[N],ans=INF; void add(int u,int v,int w){e[++cnt]=(node){h[u],v,w},h[u]=cnt;} #define QXX(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next) struct Node { int id;ll d; bool operator < (const Node a) const {return d>a.d;} }; priority_queue<Node>q; void dijkstra() { while(!q.empty()) q.pop(); for(int i=1;i<=t;++i) dis[i]=INF; dis[s]=0; Node a; int u,d; q.push((Node){s,0}); while(!q.empty()) { a=q.top(),q.pop(); u=a.id,d=a.d; if(d!=dis[u]) continue; QXX(u) if(dis[u]+e[i].w<dis[v]) { dis[v]=dis[u]+e[i].w; q.push((Node){v,dis[v]}); } } } void work() { ans=INF; n=read(),m=read(),k=read(); s=n+1,t=n+2; for(int i=1;i<=m;++i) x[i]=read(),y[i]=read(),z[i]=read(); for(int i=1;i<=k;++i) a[i]=read(); for(int q=0;(1<<q)<=k;++q) { memset(h,0,sizeof(h)); cnt=0; for(int i=1;i<=k;++i) { if(i&(1<<q)) add(s,a[i],0); else add(a[i],t,0); } for(int i=1;i<=m;++i) add(x[i],y[i],z[i]); dijkstra(); ans=min(ans,dis[t]); memset(h,0,sizeof(h)); cnt=0; for(int i=1;i<=k;++i) { if(i&(1<<q)) add(s,a[i],0); else add(a[i],t,0); } for(int i=1;i<=m;++i) add(y[i],x[i],z[i]); dijkstra(); ans=min(ans,dis[t]); } cout<<ans<<endl; } int main() { int T=read(); while(T--) work(); return 0; }
标签:otto -- log block jks ret src base read
原文地址:https://www.cnblogs.com/zijinjun/p/11137356.html