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\n");
136         else printf("%d\n",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 }

 

posted @ 2018-12-20 21:21  guapisolo  阅读(223)  评论(0编辑  收藏  举报