zoukankan      html  css  js  c++  java
  • BZOJ 1576 [USACO]安全路经Travel (树剖+线段树)

    题目大意:

    给你一张无向图,求1到其他节点 不经过最短路的最后一条边 的最短路长度,保证每个节点的最短路走法唯一

    神题,$USACO$题目的思维是真的好

    先$dijkstra$出最短路树

    对于每个节点,符合条件的走法必须满足,不经过它和它父亲之间的连边

    显然只能从它的某个子节点走向它,就像绕了一圈

    可以证明最优的合法路径一定只经过一条非树边,因为最短路方案唯一

    如果还经过另外一条非树边,不论这条边在哪,都肯定会绕远

    对于一条非树边$e<x,y>$,它连接了两个节点$x,y$,它们的$lca$是$f$

    显然$x$到$f$路径上的某个点$S$(除了$f$点),都存在一条合法路径,从根节点沿树边走到$y$,经过$e<x,y>$走到$x$,再向上沿树边走到$S$

    这段路径的长度是$dis_{x}+dis_{y}+dis_{e<x,y>}-dis_{S}$

    对于$y$到$f$的路径也是同理

    上面的式子可以用线段树+树链剖分序维护

      1 #include <queue>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 1010
      7 #define M1 2010
      8 #define S1 (N1<<1)
      9 #define T1 (N1<<2)
     10 #define ll long long
     11 #define uint unsigned int
     12 #define rint register int 
     13 #define dd double
     14 #define il inline 
     15 #define inf 233333333
     16 using namespace std;
     17 
     18 int gint()
     19 {
     20     int ret=0,fh=1;char c=getchar();
     21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     23     return ret*fh;
     24 }
     25 int n,m;
     26 struct Edge{
     27 int to[M1*2],nxt[M1*2],val[M1*2],head[N1],cte;
     28 void ae(int u,int v,int w)
     29 {cte++,to[cte]=v,nxt[cte]=head[u],val[cte]=w,head[u]=cte;}
     30 }E,T;
     31 struct SEG{
     32 int mi[T1];
     33 void pushdown(int rt)
     34 {
     35     mi[rt<<1]=min(mi[rt<<1],mi[rt]);
     36     mi[rt<<1|1]=min(mi[rt<<1|1],mi[rt]);
     37 }
     38 void build(int l,int r,int rt)
     39 {
     40     mi[rt]=inf; 
     41     if(l==r) return;
     42     int mid=(l+r)>>1;
     43     build(l,mid,rt<<1);
     44     build(mid+1,r,rt<<1|1);
     45 }
     46 void update(int L,int R,int l,int r,int rt,int w)
     47 {
     48     if(L<=l&&r<=R) {mi[rt]=min(mi[rt],w);return;}
     49     int mid=(l+r)>>1; pushdown(rt);
     50     if(L<=mid) update(L,R,l,mid,rt<<1,w);
     51     if(R>mid) update(L,R,mid+1,r,rt<<1|1,w);
     52 }
     53 int query(int x,int l,int r,int rt)
     54 {
     55     if(l==r) return mi[rt];
     56     int mid=(l+r)>>1; pushdown(rt);
     57     if(x<=mid) return query(x,l,mid,rt<<1);
     58     else return query(x,mid+1,r,rt<<1|1);
     59 }
     60 }s;
     61 
     62 int dis[N1],use[N1],fa[N1],la[N1],ist[M1*2];
     63 struct node{
     64     int id,d;
     65     friend bool operator < (const node &s1,const node &s2)
     66     {return s1.d>s2.d;}
     67 };
     68 void dijkstra()
     69 {
     70     int j,v,u;
     71     memset(dis,0x3f,sizeof(dis));
     72     priority_queue<node>q;
     73     dis[1]=0,q.push((node){1,0});
     74     while(!q.empty())
     75     {
     76         node k=q.top(); q.pop(); u=k.id;
     77         if(use[u]) continue; use[u]=1;
     78         for(j=E.head[u];j;j=E.nxt[j]){
     79             v=E.to[j];
     80             if(dis[v]>dis[u]+E.val[j])
     81                 dis[v]=dis[u]+E.val[j],q.push((node){v,dis[v]}),fa[v]=u,la[v]=j;
     82         }
     83     }
     84 }
     85 
     86 int dep[N1],sz[N1],tp[N1],son[N1],st[N1],id[N1],tot;
     87 void dfs1(int u,int dad)
     88 {
     89     for(int j=T.head[u];j;j=T.nxt[j])
     90     {
     91         int v=T.to[j]; if(v==dad) continue;
     92         dep[v]=dep[u]+1; dfs1(v,u); //fa[v]=u;
     93         sz[u]+=sz[v]; son[u]=sz[v]>sz[son[u]]?v:son[u];
     94     }
     95     sz[u]++;
     96 }
     97 void dfs2(int u)
     98 {
     99     st[u]=++tot,id[tot]=u;
    100     if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]);
    101     for(int j=T.head[u];j;j=T.nxt[j])
    102     {
    103         int v=T.to[j];
    104         if(v==son[u]||v==fa[u]) continue;
    105         tp[v]=v; dfs2(v);
    106     }
    107 }
    108 void update(int x,int y,int w)
    109 {
    110     int px=x,py=y;
    111     while(tp[x]!=tp[y])
    112     {
    113         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    114         s.update(st[tp[x]],st[x],1,n,1,dis[px]+dis[py]+w);
    115         x=fa[tp[x]];
    116     }
    117     if(dep[x]>dep[y]) swap(x,y);
    118     if(x!=y) s.update(st[x]+1,st[y],1,n,1,dis[px]+dis[py]+w);
    119 }
    120 
    121 void solve()
    122 {
    123     int x,y,i,j,v,ans; dijkstra(); s.build(1,n,1);
    124     for(i=2;i<=n;i++) T.ae(fa[i],i,E.val[la[i]]),ist[la[i]]=1;
    125     dep[1]=1,dfs1(1,-1); tp[1]=1,dfs2(1);
    126     for(j=2;j<=m*2;j+=2)
    127     {
    128         if(ist[j]||ist[j+1]) continue;
    129         x=E.to[j],y=E.to[j+1];
    130         update(x,y,E.val[j]);
    131     }
    132     for(i=2;i<=n;i++)
    133     {
    134         ans=s.query(st[i],1,n,1);
    135         if(ans==inf) printf("-1
    ");
    136         else printf("%d
    ",ans-dis[i]);
    137     }
    138 }
    139 
    140 int main()
    141 {
    142     scanf("%d%d",&n,&m);
    143     int i,j,x,y,z;E.cte=1;
    144     for(i=1;i<=m;i++) x=gint(),y=gint(),z=gint(),E.ae(x,y,z),E.ae(y,x,z);
    145     solve();
    146     return 0;
    147 }
  • 相关阅读:
    vim复制
    嵌入式Linux学习(二)
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1025 数的划分
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10152514.html
Copyright © 2011-2022 走看看