bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集
Posted third2333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集相关的知识,希望对你有一定的参考价值。
bzoj4144 [AMPPZ2014]Petrol
图论 最短路 并查集
1、这道题我们主要就是要求出距离一个油站的最近的油站
首先我们dijkstra 求出任意一个点到 离他最近的油站的距离
2、然后会发现 如果一条边的两个端点 的最近油站不同的话
那么这条边就会在这两个油站的最短路上
3、然后对于每一条边 我们将他的权值 变为
dis[ u ] + dis[ v ] + e[ i ][ j ]
如果u与v最近油站相同 那么这个无意义
如果不同 那么久表示 u 最近油站 到 v 最近油站的最近距离
4、然后我们就 排下序
离线做 取出 满足 最多加油的边 并查集 维护一下连通性就行了
1 #include <bits/stdc++.h> 2 using namespace std ; 3 4 const int N = 200011,inf = 1e9 ; 5 struct edge{ 6 int to,pre,val ; 7 }e[N*2]; 8 struct ek{ 9 int x,y,dis ; 10 }te[N]; 11 int vis[N],head[N],dis[N],c[N],ans[N],fa[N],rank[N] ; 12 int n,m,Q,s,cnt,now ; 13 14 struct node{ 15 int val,pos ; 16 }p ; 17 struct cmp{ 18 bool operator() (node a,node b ) 19 { 20 return a.val > b.val ; 21 } 22 }; 23 struct qu{ 24 int s,t,b,id ; 25 }q[N] ; 26 27 inline int read() 28 { 29 int x = 0 , f = 1 ; 30 char ch = getchar() ; 31 while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) f = -1 ; ch = getchar() ; } 32 while(ch>=‘0‘&&ch<=‘9‘) { x = x * 10+ch-48 ; ch = getchar() ; } 33 return x * f ; 34 } 35 36 inline void add(int x,int y,int v) 37 { 38 e[++cnt].to = y ; 39 e[cnt].pre = head[x] ; 40 e[cnt].val = v ; 41 head[ x ] = cnt ; 42 } 43 44 inline void dij() 45 { 46 priority_queue <node,vector<node>,cmp> Q ; 47 for(int i=1;i<=n;i++) vis[ i ] = 0 ,dis[ i ] = inf ; 48 int u,v ; 49 for(int i=1;i<=s;i++) 50 { 51 p.val = 0 ; p.pos = c[ i ] ; 52 Q.push(p) ; dis[ c[ i ] ] = 0 ; 53 } 54 while(!Q.empty()) 55 { 56 u = Q.top().pos ; 57 Q.pop() ; 58 if( vis[ u ] ) continue ; 59 vis[ u ] = 1 ; 60 for(int i=head[u];i;i=e[i].pre) 61 { 62 v = e[ i ].to ; 63 if( dis[ u ] + e[ i ].val < dis[ v ] ) 64 { 65 dis[ v ] = dis[ u ] + e[ i ].val ; 66 p.pos = v ; p.val = dis[ v ] ; 67 Q.push( p ) ; 68 } 69 } 70 } 71 } 72 73 inline bool cmp1(ek a,ek b) { return a.dis < b.dis ; } 74 inline bool cmp2(qu a,qu b) { return a.b < b.b ; } 75 76 inline int find(int x) 77 { 78 if(x==fa[x]) return x ; 79 return fa[ x ] = find(fa[x]) ; 80 } 81 82 inline void Union(int x,int y) 83 { 84 x = find(x) ; y = find(y) ; 85 if(x==y) return ; 86 if(rank[ x ] > rank[ y ]) swap(x,y) ; 87 fa[ x ] = y ; 88 rank[y]+= rank[x]==rank[y] ; 89 } 90 91 int main() 92 { 93 n = read() ; s = read() ; m = read() ; 94 for(int i=1;i<=s;i++) c[ i ] = read() ; 95 int x,y,v ; 96 for(int i=1;i<=m;i++) 97 { 98 x = read() ; y = read() ; v = read() ; 99 te[ i ] = (ek){ x,y,v } ; 100 add(x,y,v) ; 101 add(y,x,v) ; 102 } 103 dij() ; 104 for(int i=1;i<=m;i++) 105 te[ i ].dis = dis[ te[ i ].x ] + dis[ te[ i ].y ] + te[ i ].dis; 106 Q = read() ; 107 for(int i=1;i<=Q;i++) 108 q[ i ].s = read() ,q[ i ].t = read() ,q[ i ].b = read(),q[ i ].id = i ; 109 110 for(int i=1;i<=n;i++) 111 fa[ i ] = i ,rank[ i ] = 0 ; 112 sort( te+1,te+m+1,cmp1 ) ; 113 sort( q+1,q+Q+1,cmp2 ) ; 114 now = 1 ; 115 for(int i=1;i<=Q;i++) 116 { 117 while(now<=m&&te[ now ].dis <= q[ i ].b) 118 { 119 Union( te[ now ].x,te[ now ].y ) ; 120 now++ ; 121 } 122 ans[ q[ i ].id ] = find( q[ i ].s ) == find(q[ i ].t) ; 123 } 124 for(int i=1;i<=Q;i++) 125 puts(ans[ i ] ? "TAK" : "NIE" ) ; 126 return 0 ; 127 }
以上是关于bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ4144[AMPPZ2014]Petrol 最短路+离线+最小生成树
4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)