zoukankan      html  css  js  c++  java
  • 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)

    4144: [AMPPZ2014]Petrol

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 752  Solved: 298
    [Submit][Status][Discuss]

    Description

    给定一个n个点、m条边的带权无向图,其中有s个点是加油站。
    每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满。
    q次询问,每次给出x,y,b,表示出发点是x,终点是y,油量上限为b,且保证x点和y点都是加油站,请回答能否从x走到y。
     

    Input

    第一行包含三个正整数n,s,m(2<=s<=n<=200000,1<=m<=200000),表示点数、加油站数和边数。
    第二行包含s个互不相同的正整数c[1],c[2],...c[s](1<=c[i]<=n),表示每个加油站。
    接下来m行,每行三个正整数u[i],v[i],d[i](1<=u[i],v[i]<=n,u[i]!=v[i],1<=d[i]<=10000),表示u[i]和v[i]之间有一条长度为d[i]的双向边。
    接下来一行包含一个正整数q(1<=q<=200000),表示询问数。
    接下来q行,每行包含三个正整数x[i],y[i],b[i](1<=x[i],y[i]<=n,x[i]!=y[i],1<=b[i]<=2*10^9),表示一个询问。
     

    Output

    输出q行。第i行输出第i个询问的答案,如果可行,则输出TAK,否则输出NIE。
     

    Sample Input

    6 4 5
    1 5 2 6
    1 3 1
    2 3 2
    3 4 3
    4 5 5
    6 4 5
    4
    1 2 4
    2 6 9
    1 5 9
    6 5 8

    Sample Output

    TAK
    TAK
    TAK
    NIE

    HINT

     

    Source

    鸣谢Claris上传


    朴素是先写个多源最短路把加油站的最小生成树所有可能边弄出来,然后后面按部就班地建个最小生成树,然后对树上写个主席树(st倍增)找u到v上最大值,和b比较一下。

    那我们在把所有可能边弄出来以后停一下2333,我们连边不要对这条边俩端点连,而是对他们所在块的堆头节点连,这个建出来在查询最大值上是等效的。然后我们启发式地合并堆,这样可以把堆高度控制在logn,就不用再写个主席树啥的那麻烦了。直接两个端点往上一个一个跳,logn的不会有事的。

      1 #include<bits/stdc++.h>
      2 #define clr(x) memset(x,0,sizeof(x))
      3 #define clr_1(x) memset(x,-1,sizeof(x))
      4 #define INF 0x3f3f3f3f
      5 #define LL long long
      6 #define pb push_back
      7 #define mod 1000000007
      8 #define ls(i) (i<<1)
      9 #define rs(i) (i<<1|1)
     10 #define mp make_pair
     11 #define fi first
     12 #define se second
     13 using namespace std;
     14 typedef pair<LL,int > pli;
     15 const int N = 2e5+10;
     16 bool need[N];
     17 vector<pli> e[N];
     18 struct node
     19 {
     20     int u,v;
     21     LL w;
     22     node(int _u=0,int _v=0,LL _w=0):u(_u),v(_v),w(_w) {}
     23 };
     24 vector<node> ve;
     25 int n,s,m,T;
     26 priority_queue<pli,vector<pli>,greater<pli> > que;
     27 int fuel[N];
     28 int fa[N],rfa[N],rk[N],dep[N];
     29 LL dis[N],val[N];
     30 bool vis[N];
     31 int pre[N];
     32 void dij()
     33 {
     34     while(!que.empty())
     35     {
     36         pli now=que.top();
     37         que.pop();
     38         LL dist=now.fi;
     39         int u=now.se;
     40         if(vis[u]) continue;
     41         vis[u]=1;
     42         int sz=e[u].size();
     43         for(int i=0;i<sz;i++)
     44         {
     45             pli p=e[u][i];
     46             int w=p.fi;
     47             int v=p.se;
     48             if(!pre[v] || dis[v]>dis[u]+w)
     49             {
     50                 dis[v]=dis[u]+w;
     51                 pre[v]=pre[u];
     52                 que.push(mp(dis[v],v));
     53             }
     54             else if(pre[u] != pre[v])
     55                 ve.pb(node(pre[u],pre[v],dis[u]+dis[v]+w));
     56         }
     57     }
     58     return ;
     59 }
     60 bool cmp(node a,node b)
     61 {
     62     return a.w<b.w;
     63 }
     64 int Find(int u)
     65 {
     66     if(fa[u]!=u)
     67         fa[u]=Find(fa[u]);
     68     return fa[u];
     69 }
     70 void Union()
     71 {
     72     sort(ve.begin(),ve.end(),cmp);
     73     for(int i=1;i<=s;i++)
     74     {
     75         fa[fuel[i]]=fuel[i];
     76         rk[fuel[i]]=1;
     77     }
     78     int sz=ve.size();
     79     for(int i=0;i<sz;i++)
     80     {
     81         node p=ve[i];
     82         int u = p.u, v = p.v;
     83         LL w = p.w;
     84         u = Find(u), v = Find(v);
     85         if(u==v) continue;
     86         if(rk[u]<rk[v]) swap(u,v);
     87         if(rk[u]==rk[v]) rk[u]++;
     88         rfa[v]=u,fa[v]=u,val[v]=w;
     89     }
     90     return ;
     91 }
     92 void dealdep(int u)
     93 {
     94     if(dep[u]>0) return ;
     95     if(fa[u]==u)
     96     {
     97         dep[u]=1;
     98         return ;
     99     }
    100     dealdep(rfa[u]);
    101     dep[u]=dep[rfa[u]]+1;
    102     return ;
    103 }
    104 bool solve(int u,int v,LL b)
    105 {
    106     if(Find(u)!=Find(v)) return 0;
    107     if(dep[u]<dep[v]) swap(u,v);
    108     while(dep[u]>dep[v])
    109     {
    110         if(b<val[u]) return 0;
    111         u=rfa[u];
    112     }
    113     if(u==v) return 1;
    114     while(u!=v)
    115     {
    116         if(b<val[u]) return 0;
    117         if(b<val[v]) return 0;
    118         u=rfa[u];
    119         v=rfa[v];
    120     }
    121     return 1;
    122 }
    123 int main()
    124 {
    125     scanf("%d%d%d",&n,&s,&m);
    126     clr_1(dis);
    127     for(int i=1;i<=s;i++)
    128     {
    129         scanf("%d",fuel+i);
    130         que.push(mp(0,fuel[i]));
    131         pre[fuel[i]]=fuel[i];
    132         dis[fuel[i]]=0;
    133     }
    134     for(int i=1;i<=m;i++)
    135     {
    136         int u,v;
    137         LL w;
    138         scanf("%d%d%lld",&u,&v,&w);
    139         e[u].pb(mp(w,v));
    140         e[v].pb(mp(w,u));
    141     }
    142     dij();
    143     Union();
    144     for(int i=1;i<=s;i++)
    145         dealdep(fuel[i]);
    146     int u,v;
    147     LL b,maxn;
    148     int q;
    149     scanf("%d",&q);
    150     while(q--)
    151     {
    152         scanf("%d%d%lld",&u,&v,&b);
    153         if(solve(u,v,b))
    154             printf("TAK
    ");
    155         else
    156             printf("NIE
    ");
    157     }
    158     return 0;
    159 }
    View Code
  • 相关阅读:
    css:清除浮动
    js获得页面鼠标位置
    用jquery实现小火箭到页面顶部的效果
    PHP自动测试框架Top 10
    我的linux一万小时
    10个技巧优化PHP程序Laravel 5框架
    PHP开发中涉及到emoji表情的几种处理方法
    PHP编程效率的20个要点--PHP技术教程分享
    PHP中9大缓存技术总结
    【风马一族_xml】xml语法
  • 原文地址:https://www.cnblogs.com/wujiechao/p/9170670.html
Copyright © 2011-2022 走看看