zoukankan      html  css  js  c++  java
  • bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    【题意】

        给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠。

    【思路】

        首先用dijkstra算法构造以1为根的最短路树。

        将一条无向边看作两条有向边,考察一条不在最短路树上的边(u,v),如果我们连接(u,v) ,设t=lct(u,v),则为v->t(不含t)路径上的点提供了另外一条1-x的路径且最后一条边不与最短路重合,这条路径长度为dis[u]+dis[v]+e.w-dis[x],对于每个点维护最小的mn=dis[u]+dis[v]+e.w,因为每次需要对一条路径进行修改,所以可以用树链剖分+线段树维护最小值和一个懒标记完成。

        好题。。。

       

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 const int N = 2e5+10;
     15 const int M = 4e5+10;
     16 const int inf = 1e9;
     17 
     18 ll read() {
     19     char c=getchar();
     20     ll f=1,x=0;
     21     while(!isdigit(c)) {
     22         if(c=='-') f=-1; c=getchar();
     23     }
     24     while(isdigit(c))
     25         x=x*10+c-'0',c=getchar();
     26     return x*f;
     27 }
     28 
     29 struct Edge {
     30     int u,v,w,nxt;
     31 }e[M];
     32 int en=1,front[N];
     33 void adde(int u,int v,int w) {
     34     e[++en]=(Edge){u,v,w,front[u]}; front[u]=en;
     35 }
     36 
     37 struct Node {
     38     int id,dis;
     39     bool operator < (const Node& rhs) const {
     40         return dis>rhs.dis;
     41     }
     42 };
     43 
     44 struct Tnode {
     45     int u,l,r,mn,tag;
     46     void minv(int x);
     47     void pushdown();
     48     void maintain();
     49 }T[N<<1];
     50 void Tnode::minv(int x) {
     51     tag=x;
     52     mn=min(mn,x);
     53 }
     54 void Tnode:: pushdown() {
     55     if(tag!=-1 && l!=r) {
     56         T[u<<1].minv(tag);
     57         T[u<<1|1].minv(tag);
     58         tag=-1;
     59     }
     60 }
     61 void Tnode:: maintain() {
     62     if(l==r) return ;
     63     mn=min(T[u<<1].mn,T[u<<1|1].mn);
     64 }
     65 
     66 priority_queue<Node> q;
     67 int n,m;
     68 int SZ,vis[N],dis[N],dep[N],siz[N],son[N],fa[N],top[N],mark[N],p[N],pl[N];
     69 
     70 void dijkstra()
     71 {
     72     FOR(i,0,n) dis[i]=inf;
     73     dis[1]=0;
     74     q.push((Node){1,0});
     75     while(!q.empty()) {
     76         int u=q.top().id; q.pop();
     77         if(vis[u]) continue;
     78         vis[u]=1;
     79         trav(u,i) {
     80             int v=e[i].v;
     81             if(dis[v]>dis[u]+e[i].w) {
     82                 dis[v]=dis[u]+e[i].w;
     83                 mark[p[v]]=0; mark[i]=1;
     84                 p[v]=i;
     85                 q.push((Node){v,dis[v]});
     86             }
     87         }
     88     }
     89 }
     90 void dfs1(int u)
     91 {
     92     siz[u]=1; son[u]=0;
     93     trav(u,i) if(mark[i]) {
     94         int v=e[i].v;
     95         if(v!=fa[u]) {
     96             fa[v]=u;
     97             dep[v]=dep[u]+1;
     98             dfs1(v);
     99             siz[u]+=siz[v];
    100             if(siz[v]>siz[son[u]]) son[u]=v;
    101         }
    102     }
    103 }
    104 void dfs2(int u,int tp)
    105 {
    106     top[u]=tp; pl[u]=++SZ;
    107     if(son[u]) dfs2(son[u],tp);
    108     trav(u,i) if(mark[i]&&e[i].v!=fa[u])
    109         dfs2(e[i].v,e[i].v);
    110 }
    111 int lca(int u,int v) {
    112     while(top[u]!=top[v]) {
    113         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    114         u=fa[top[u]];
    115     }
    116     return dep[u]<dep[v]? u:v;
    117 }
    118 void build(int u,int l,int r)
    119 {
    120     T[u]=(Tnode) {u,l,r,inf,-1};
    121     if(l==r) return ;
    122     int mid=l+r>>1;
    123     build(u<<1,l,mid),
    124     build(u<<1|1,mid+1,r);
    125 }
    126 void update(int u,int L,int R,int x)
    127 {
    128     T[u].pushdown();
    129     if(L<=T[u].l&&T[u].r<=R) T[u].minv(x);
    130     else {
    131         int mid=T[u].l+T[u].r>>1;
    132         if(L<=mid) update(u<<1,L,R,x);
    133         if(mid<R)  update(u<<1|1,L,R,x);
    134         T[u].maintain();
    135     }
    136 }
    137 int query(int u,int x)
    138 {
    139     T[u].pushdown();
    140     if(T[u].l==T[u].r) return T[u].mn;
    141     else {
    142         int mid=T[u].l+T[u].r>>1;
    143         if(x<=mid) return query(u<<1,x);
    144         else return query(u<<1|1,x);
    145     }
    146 }
    147 
    148 void modify(int u,int v,int x)
    149 {
    150     while(top[u]!=top[v]) {
    151         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    152         update(1,pl[top[u]],pl[u],x);
    153         u=fa[top[u]];
    154     }
    155     if(dep[u]>dep[v]) swap(u,v);
    156     update(1,pl[u],pl[v],x);
    157 }
    158 
    159 int main()
    160 {
    161     n=read(),m=read();
    162     int u,v,w;
    163     FOR(i,1,m) {
    164         u=read(),v=read(),w=read();
    165         adde(u,v,w),adde(v,u,w);
    166     }
    167     dijkstra();
    168     dfs1(1),dfs2(1,1);
    169     build(1,1,SZ);
    170     for(int i=2;i<=en;i+=2) {
    171         u=e[i].u,v=e[i].v,w=e[i].w;
    172         int LCA=lca(u,v);
    173         if(!mark[i]) modify(v,LCA,dis[u]+dis[v]+e[i].w);
    174         if(!mark[i^1]) modify(u,LCA,dis[u]+dis[v]+e[i].w);
    175     }
    176     FOR(i,2,n) {
    177         w=query(1,pl[i]);
    178         if(w==inf) puts("-1");
    179         else printf("%d
    ",w-dis[i]);
    180     }
    181     return 0;
    182 }
  • 相关阅读:
    Selenium学习:鼠标事件
    Selenium学习:新窗口打开链接,并定位到新窗口
    Selenium学习:get_attribute()方法获取列表元素信息
    Java 基础(接口二)
    Java 基础(接口一)
    Java 练习(模板方法设计模式TemplateMethod)
    Java 基础(多态的应用:模板方法设计模式TemplateMethod)
    Java 基础(抽象类的匿名子类)
    Java 练习(抽象类与抽象方法)
    Java 基础( final 关键字)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5324960.html
Copyright © 2011-2022 走看看