【xsy1300】 原題的旅行 最短路+倍增

題目大意:有一個$n$個點,$m$條邊的無向圖,玩家走過第$i$條邊,血槽中的血會降低$v_i$點,若是不足$v_i$點,這人會當場去世。node

這$n$個點中,有若干個是關鍵點,在這些關鍵點能夠將血槽補滿。c++

如今有$q$組詢問,每次問一個玩家的血槽至少須要多大,才能從$x$走到$y$。spa

保證$x$號點和$y$號點能夠把你的血槽補滿code

數據範圍:$n≤10^5$,$m≤2\times 10^5$,$V≤10^9$。blog

 

咱們考慮若是每一個點都能補滿血槽的話,咱們顯然能夠對原圖求一遍最小生成樹,每次咱們在這顆樹上倍增取最大值便可。get

不過這一題很是煩人,只有一部分點是能夠的。it

咱們考慮對每一個點i處理出$dist[i]$和$from[i]$。io

其中,$from[i]$表示距離$i$號點最近的能夠補滿$i$號點血槽的點的編號,$dist[i]$表示$i$號點距離$from[i]$的距離。class

對於原圖中任意一條邊$(u,v,w)$,若知足$from[u]!=from[v]$,那麼咱們就在新圖中加入$(from[u],from[v],dist[u]+dist[v]+w)$queue

而後,咱們對新圖求一個最小生成樹,而後在這棵樹上倍增便可。

時間複雜度顯然是$O((m+n+q)\log\ n)$的。

 

 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define M 200005
 4 #define INF (1LL<<60)
 5 using namespace std;
 6 
 7 struct edge{L u,v,next;}e[M*4]={0}; L head[M]={0},use=0;
 8 void add(L x,L y,L z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
 9 L dist[M]={0},from[M]={0};
10 L n,m; L ok[M]={0},vis[M]={0};char c[M]={0};
11 
12 struct node{
13     L u,bel; L dis;
14     node(){u=bel=dis=0;}
15     node(L U,L Bel,L Dis){u=U; bel=Bel; dis=Dis;}
16     friend bool operator <(node a,node b){
17         return a.dis>b.dis;
18     }
19 }; priority_queue<node> q;
20 
21 void dij(){
22     memset(dist,1,sizeof(dist));
23     for(L i=1;i<=n;i++) if(ok[i]) q.push(node(i,i,0));
24     while(!q.empty()){
25         node U=q.top(); q.pop();
26         L u=U.u; if(dist[u]!=dist[0]) continue;
27         dist[u]=U.dis; 
28         from[u]=U.bel;
29         for(L i=head[u];i;i=e[i].next)
30         if(dist[u]+e[i].v<=dist[e[i].u]){
31             q.push(node(e[i].u,U.bel,dist[u]+e[i].v));
32         }
33     }
34 }
35 
36 struct edge2{
37     L u,v;L w;
38     edge2(){u=v=w=0;}
39     edge2(L U,L V,L W){u=U; v=V; w=W;}
40     friend bool operator <(edge2 a,edge2 b){return a.w<b.w;}
41 }p[M*2]; L N=0;
42 
43 L fa[M]={0}; L get(L x){return x==fa[x]?x:fa[x]=get(fa[x]);}
44 
45 L f[M][20]={0},dep[M]={0}; L mx[M][20]={0};
46 void dfs(L x,L fa,L F){
47     f[x][0]=fa; dep[x]=dep[fa]+1; mx[x][0]=F;
48     for(L i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1],mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]);
49     for(L i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x,e[i].v);
50 }
51 L getlca(L x,L y){
52     if(dep[x]<dep[y]) swap(x,y); L cha=dep[x]-dep[y];
53     for(L i=19;~i;i--) if((1<<i)&cha) x=f[x][i];
54     for(L i=19;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
55     if(x==y) return x; return f[x][0];
56 }
57 L jump(L x,L k){
58     L maxn=0;
59     for(L i=19;~i;i--) if((1<<i)&k){
60         maxn=max(maxn,mx[x][i]);
61         x=f[x][i];
62     }
63     return maxn;
64 }
65 
66 main(){
67     scanf("%lld%lld",&n,&m);
68     scanf("%s",c+1); for(L i=1;i<=n;i++) ok[i]=(c[i]=='1');
69     for(L i=1,x,y,z;i<=m;i++) scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add(y,x,z);
70     dij();
71     for(L x=1;x<=n;x++)
72     for(L i=head[x];i;i=e[i].next) if(i&1){
73         L X=x,Y=e[i].u;
74         if(from[X]!=from[Y]){
75             p[++N]=edge2(from[X],from[Y],dist[X]+dist[Y]+e[i].v);
76         }
77     }
78     sort(p+1,p+N+1);
79     memset(head,0,sizeof(head)); use=0; memset(e,0,sizeof(e));
80     for(L i=1;i<=n;i++) fa[i]=i;
81     
82     for(L i=1;i<=N;i++){
83         L u=get(p[i].u),v=get(p[i].v);
84         if(u==v) continue; fa[u]=v;
85         u=p[i].u; v=p[i].v;
86         add(u,v,p[i].w); add(v,u,p[i].w);
87     }
88     L sta=0; for(L i=1;i<=n;i++) if(ok[i]) {sta=i; break;}
89     
90     dfs(sta,0,0);
91     
92     L q; scanf("%lld",&q);
93     while(q--){
94         L x,y; scanf("%lld%lld",&x,&y);
95         L lca=getlca(x,y);
96         printf("%lld\n",max(jump(x,dep[x]-dep[lca]),jump(y,dep[y]-dep[lca])));
97     }
98 }
相關文章
相關標籤/搜索