• 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 }
  • 相关阅读:
    jieba库的使用和词云
    类和正则表达
    数据库实践
    自己的第一个网页
    第一个爬虫和测试
    Linux 知识总结
    Python argparse模块基本用法
    Python面向对象编程
    linux Nginx发布基于PHP的WEB
    Linux nginx发布基于python的WEB环境
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10152514.html
Copyright © 2020-2023  润新知