zoukankan      html  css  js  c++  java
  • 数据结构(左偏树,可并堆):BNUOJ 3943 Safe Travel

    Safe Travel

    Time Limit: 3000ms
    Memory Limit: 65536KB
    64-bit integer IO format: %lld      Java class name: Main
      Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 to pasture_i. Each gremlin is personalized and knows the quickest path that cow_i normally takes to pasture_i. Gremlin_i waits for cow_i in the middle of the final cowpath of the quickest route to pasture_i, hoping to harass cow_i.

      Each of the cows, of course, wishes not to be harassed and thus chooses an at least slightly different route from pasture_1 (the barn) to pasture_i.

      Compute the best time to traverse each of these new not-quite-quickest routes that enable each cow_i that avoid gremlin_i who is located on the final cowpath of the quickest route from pasture_1 to pasture_i.

      As usual, the M (2 <= M <= 200,000) cowpaths conveniently numbered 1..M are bidirectional and enable travel to all N (3 <= N <= 100,000) pastures conveniently numbered 1..N. Cowpath i connects pastures a_i (1 <= a_i <= N) and b_i (1 <= b_i <= N) and requires t_i (1 <= t_i <= 1,000) time to traverse. No two cowpaths connect the same two pastures, and no path connects a pasture to itself (a_i != b_i).
    Best of all, the shortest path regularly taken by cow_i from pasture_1 to pasture_i is unique in all the test data supplied to your program.

      By way of example, consider these pastures, cowpaths, and [times]:

         1----[2]----2---+
         |     |         |
        [2]   [1]       [3]
         |     |         |
         +-----3---[4]---4

      TRAVEL     BEST ROUTE   BEST TIME   LAST PATH
    p_1 to p_2       1->2          2         1->2
    p_1 to p_3       1->3          2         1->3
    p_1 to p_4      1->2->4        5         2->4

    When gremlins are present:

      TRAVEL     BEST ROUTE   BEST TIME    AVOID
    p_1 to p_2     1->3->2         3         1->2
    p_1 to p_3     1->2->3         3         1->3
    p_1 to p_4     1->3->4         6         2->4

     

    Input

      * Line 1: Two space-separated integers: N and M

      * Lines 2..M+1: Three space-separated integers: a_i, b_i, and t_i
     

    Output

      * Lines 1..N-1: Line i contains the smallest time required to travel from pasture_1 to pasture_i+1 while avoiding the final cowpath of the shortest path from pasture_1 to pasture_i+1. If no such path exists from pasture_1 to pasture_i+1, output -1 alone on the line.
     

    Sample Input

    4 5
    1 2 2
    1 3 2
    3 4 4
    3 2 1
    2 4 3
    

    Sample Output

    3
    3
    6
      
      这道题是世界上第一道树链剖分的题目,我用左偏树AC了。
      考虑先建一棵最短路树,一个点去掉树边后,它到根节点的距离就由它的子节点和它自己由非树边连到它这棵子树外的节点来更新,可以维护可并堆。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue> 
      5 using namespace std;
      6 const int maxn=100010;
      7 const int maxm=400010;
      8 int cnt,fir[maxn],to[maxm],nxt[maxm],val[maxm];
      9 void addedge(int a,int b,int c){
     10     nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;val[cnt]=c;
     11 }
     12 
     13 int tot,rt[maxm],key[maxm],lik[maxm],ch[maxm][2],dep[maxm];
     14 int ans[maxn],dis[maxn],add[maxm];
     15 
     16 void Add(int x,int d){
     17     if(!x)return;
     18     key[x]+=d;
     19     add[x]+=d;
     20 }
     21 
     22 void Push_down(int x){
     23     Add(ch[x][0],add[x]);
     24     Add(ch[x][1],add[x]);
     25     add[x]=0;
     26 }
     27 
     28 int Merge(int x,int y){
     29     if(!x||!y)return x|y;
     30     if(key[x]>key[y])swap(x,y);
     31     Push_down(x);
     32     ch[x][1]=Merge(ch[x][1],y);
     33     if(dep[ch[x][0]]<dep[ch[x][1]])
     34         swap(ch[x][0],ch[x][1]);
     35     dep[x]=dep[ch[x][1]]+1;
     36     return x;    
     37 }
     38 
     39 void Delete(int node){
     40     Push_down(rt[node]);
     41     rt[node]=Merge(ch[rt[node]][0],ch[rt[node]][1]);
     42 }
     43 
     44 int ID[maxn],end[maxn],id;
     45 
     46 void DFS(int node){
     47     ID[node]=++id;
     48     for(int i=fir[node];i;i=nxt[i])
     49         if(dis[to[i]]==dis[node]+val[i])
     50             DFS(to[i]);
     51     end[node]=id;
     52 }
     53 
     54 void Solve(int node){
     55     for(int i=fir[node];i;i=nxt[i]){
     56         if(dis[to[i]]==dis[node]+val[i]){
     57             Solve(to[i]);
     58             Add(rt[to[i]],val[i]);
     59             rt[node]=Merge(rt[node],rt[to[i]]);
     60         }
     61         else{
     62             if(dis[to[i]]+val[i]==dis[node])continue;
     63             if(ID[to[i]]<=end[node]&&ID[to[i]]>=ID[node])continue;
     64             key[++tot]=dis[to[i]]+val[i];lik[tot]=to[i];
     65             rt[node]=Merge(rt[node],tot);
     66         }
     67     }
     68     while(rt[node]&&ID[lik[rt[node]]]<=end[node]&&ID[lik[rt[node]]]>=ID[node]){
     69         Delete(node);
     70     }
     71     if(rt[node])
     72     ans[node]=key[rt[node]];
     73 }
     74 struct Node{
     75     int d,n;
     76     Node(int d_=0,int n_=0){
     77         d=d_;n=n_;
     78     }
     79     bool operator <(const Node &b)const{
     80         return d>b.d;
     81     }
     82 };
     83 
     84 priority_queue <Node,vector<Node> >q;
     85 
     86 
     87 int main(){
     88     freopen("travel.in","r",stdin);
     89     freopen("travel.out","w",stdout);
     90     int n,m;
     91     dep[0]=-1;
     92     scanf("%d%d",&n,&m);
     93     for(int i=1,a,b,c;i<=m;i++){
     94         scanf("%d%d%d",&a,&b,&c);
     95         addedge(a,b,c);
     96         addedge(b,a,c);
     97     }
     98     memset(dis,63,sizeof(dis));
     99     q.push(Node(0,1));dis[1]=0;
    100     while(!q.empty()){
    101         Node x=q.top();q.pop();
    102         for(int i=fir[x.n];i;i=nxt[i]){
    103             if(dis[x.n]+val[i]<dis[to[i]]){
    104                 dis[to[i]]=dis[x.n]+val[i];
    105                 q.push(Node(dis[to[i]],to[i]));
    106             }
    107         }
    108     }
    109     DFS(1);
    110     Solve(1);
    111     for(int i=2;i<=n;i++)
    112         printf("%d
    ",ans[i]==0?-1:ans[i]);
    113     return 0;
    114 }
    尽最大的努力,做最好的自己!
  • 相关阅读:
    阿里消息队列中间件 RocketMQ 源码分析 —— Message 拉取与消费(上)
    数据库中间件 ShardingJDBC 源码分析 —— SQL 解析(三)之查询SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(六)之删除SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(五)之更新SQL
    消息队列中间件 RocketMQ 源码分析 —— Message 存储
    源码圈 300 胖友的书单整理
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(一)分库分表配置
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(四)之插入SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(二)之分库分表路由
    C#中Math类的用法
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5360973.html
Copyright © 2011-2022 走看看