首页 > 代码库 > bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集

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 图论 最短路 并查集