zoukankan      html  css  js  c++  java
  • Bzoj 3694: 最短路 树链剖分

    3694: 最短路

    Time Limit: 5 Sec  Memory Limit: 256 MB
    Submit: 67  Solved: 34
    [Submit][Status][Discuss]

    Description

    给出一个n个点m条边的无向图,n个点的编号从1~n,定义源点为1。定义最短路树如下:从源点1经过边集T到任意一点i有且仅有一条路径,且这条路径是整个图1到i的最短路径,边集T构成最短路树。 给出最短路树,求对于除了源点1外的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径的最后一条边。
     

    Input

    第一行包含两个数n和m,表示图中有n个点和m条边。
    接下来m行,每行有四个数ai,bi,li,ti,表示图中第i条边连接ai和bi权值为li,ti为1表示这条边是最短路树上的边,ti为0表示不是最短路树上的边。

    Output

    输出n-1个数,第i个数表示从1到i+1的要求的最短路。无法到达输出-1。

    Sample Input

    5 9
    3 1 3 1
    1 4 2 1
    2 1 6 0
    2 3 4 0
    5 2 3 0
    3 2 2 1
    5 3 1 1
    3 5 2 0
    4 5 4 0

    Sample Output

    6 7 8 5

    HINT

     对于100%的数据,n≤4000,m≤100000,1≤li≤100000

    Source

    题解:
    首先,先处理出最短路树中每个点i距源点1的最短距离dis[i]。
     因为要求不经过最短路树的最后一条边,所以要到一个点,必须要从和这个点在同一个环中的另外一边绕过去。
    例如:设我们要到u点,我们还有不在最短路树上的两个点x,y。t为LCA(x,y)。假如u点在y到t的路径上,我们既然不能从1经过t到u,那我们只有从1 -> t -> x -> y ->u。这样我们可以用dis[x]+val[x][y]+dis[y]-dis[u]来更新ans。因为dis[u]是不变的,所以我们可以最后去减去dis[u]。之前只用维护dis[x]+val[x][y]+dis[y]即可。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 4010
      4 #define MAXM 100010
      5 #define INF 1e9
      6 struct node
      7 {
      8     int begin,end,value,next;
      9 }edge[MAXN*2];
     10 struct NODE
     11 {
     12     int left,right,mn,tag;
     13 }tree[MAXN*5];
     14 int cnt,Head[MAXN],n,size[MAXN],deep[MAXN],P[MAXN][12],dis[MAXN],pos[MAXN],belong[MAXN],s1[MAXM],s2[MAXM],s3[MAXM],SIZE;
     15 bool vis[MAXN];
     16 void addedge(int bb,int ee,int vv)
     17 {
     18     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
     19 }
     20 void addedge1(int bb,int ee,int vv)
     21 {
     22     addedge(bb,ee,vv);addedge(ee,bb,vv);
     23 }
     24 int read()
     25 {
     26     int s=0,fh=1;char ch=getchar();
     27     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     28     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     29     return s*fh;
     30 }
     31 void dfs1(int u)
     32 {
     33     int i,v;
     34     size[u]=1;vis[u]=true;
     35     for(i=Head[u];i!=-1;i=edge[i].next)
     36     {
     37         v=edge[i].end;
     38         if(vis[v]==false)
     39         {
     40             deep[v]=deep[u]+1;
     41             dis[v]=dis[u]+edge[i].value;
     42             P[v][0]=u;
     43             dfs1(v);
     44             size[u]+=size[v];
     45         }
     46     }
     47 }
     48 void Ycl()
     49 {
     50     int i,j;
     51     for(j=1;(1<<j)<=n;j++)
     52     {
     53         for(i=1;i<=n;i++)
     54         {
     55             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
     56         }
     57     }
     58 }
     59 void dfs2(int u,int chain)
     60 {
     61     int k=0,i,v;
     62     pos[u]=++SIZE;belong[u]=chain;
     63     for(i=Head[u];i!=-1;i=edge[i].next)
     64     {
     65         v=edge[i].end;
     66         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
     67     }
     68     if(k==0)return;
     69     dfs2(k,chain);
     70     for(i=Head[u];i!=-1;i=edge[i].next)
     71     {
     72         v=edge[i].end;
     73         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
     74     }
     75 }
     76 int LCA(int x,int y)
     77 {
     78     int i,j;
     79     if(deep[x]<deep[y])swap(x,y);
     80     for(i=0;(1<<i)<=deep[x];i++);i--;
     81     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
     82     if(x==y)return x;
     83     for(j=i;j>=0;j--)
     84     {
     85         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
     86         {
     87             x=P[x][j];
     88             y=P[y][j];
     89         }
     90     }
     91     return P[x][0];
     92 }
     93 void Build(int k,int l,int r)
     94 {
     95     tree[k].left=l;tree[k].right=r;tree[k].tag=INF;
     96     if(l==r){tree[k].mn=INF;return;}
     97     int mid=(l+r)/2;
     98     Build(k*2,l,mid);
     99     Build(k*2+1,mid+1,r);
    100 }
    101 void Pushup(int k)
    102 {
    103     int l=k*2,r=k*2+1;
    104     tree[k].mn=min(tree[l].mn,tree[r].mn);
    105 }
    106 void Pushdown(int k)
    107 {
    108     int l=k*2,r=k*2+1;
    109     if(tree[k].tag!=INF)
    110     {
    111         tree[l].tag=min(tree[l].tag,tree[k].tag);
    112         tree[r].tag=min(tree[r].tag,tree[k].tag);
    113         tree[l].mn=min(tree[l].mn,tree[k].tag);
    114         tree[r].mn=min(tree[r].mn,tree[k].tag);
    115         tree[k].tag=INF;
    116     }
    117 }
    118 void Change(int k,int l,int r,int C)
    119 {
    120     if(l<=tree[k].left&&tree[k].right<=r){tree[k].tag=min(tree[k].tag,C);tree[k].mn=min(tree[k].mn,C);return;}
    121     Pushdown(k);
    122     int mid=(tree[k].left+tree[k].right)/2;
    123     if(r<=mid)Change(k*2,l,r,C);
    124     else if(l>mid)Change(k*2+1,l,r,C);
    125     else {Change(k*2,l,mid,C);Change(k*2+1,mid+1,r,C);}
    126     Pushup(k);
    127 }
    128 void Solve_change(int x,int f,int C)
    129 {
    130     while(belong[x]!=belong[f])
    131     {
    132         Change(1,pos[belong[x]],pos[x],C);
    133         x=P[belong[x]][0];
    134     }
    135     if(x!=f)Change(1,pos[f]+1,pos[x],C);
    136 }
    137 int Query(int k,int l,int r)
    138 {
    139     if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mn;
    140     Pushdown(k);
    141     int mid=(tree[k].left+tree[k].right)/2;
    142     if(r<=mid)return Query(k*2,l,r);
    143     else if(l>mid)return Query(k*2+1,l,r);
    144     else return min(Query(k*2,l,mid),Query(k*2+1,mid+1,r));
    145 }
    146 int Solve_query(int x,int f)
    147 {
    148     int MN=INF;
    149     while(belong[x]!=belong[f])
    150     {
    151         MN=min(MN,Query(1,pos[belong[x]],pos[x]));
    152         x=P[belong[x]][0];
    153     }
    154     if(x!=f)MN=min(MN,Query(1,pos[f]+1,pos[x]));
    155     return MN;
    156 }
    157 int ask(int k,int lr)
    158 {
    159     if(tree[k].left==tree[k].right)return tree[k].mn;
    160     Pushdown(k);
    161     int mid=(tree[k].left+tree[k].right)/2;
    162     if(lr<=mid)return ask(k*2,lr);
    163     else return ask(k*2+1,lr);
    164 }
    165 int main()
    166 {
    167     int m,tot,i,a,b,l,t,lca,C;
    168     n=read();m=read();
    169     tot=0;
    170     memset(Head,-1,sizeof(Head));cnt=1;
    171     for(i=1;i<=m;i++)
    172     {
    173         a=read();b=read();l=read();t=read();
    174         if(t==0)
    175         {
    176             s1[++tot]=a;s2[tot]=b;s3[tot]=l;
    177         }
    178         else addedge1(a,b,l);
    179     }
    180     memset(P,-1,sizeof(P));SIZE=0;
    181     dfs1(1);Ycl();
    182     dfs2(1,1);
    183     Build(1,1,n);
    184     //for(i=1;i<=n;i++)Change(1,pos[i],pos[i],dis[i]);
    185     for(i=1;i<=tot;i++)
    186     {
    187         lca=LCA(s1[i],s2[i]);
    188         C=dis[s1[i]]+dis[s2[i]]+s3[i];
    189         Solve_change(s1[i],lca,C);
    190         Solve_change(s2[i],lca,C);
    191     }
    192     for(i=2;i<=n;i++)
    193     {
    194         //t=Solve_query(i,1);
    195         t=Query(1,pos[i],pos[i]);
    196         //t=ask(1,pos[i]);
    197         if(t==INF)printf("-1 ");
    198         else printf("%d ",t-dis[i]);
    199     }
    200     return 0;
    201 }
  • 相关阅读:
    C# 深浅复制 MemberwiseClone
    负载均衡算法,轮询方式
    大话设计模式之工厂模式 C#
    大话设计模式:代理模式 C#
    C# 单元测试
    【前端安全】JavaScript防http劫持与XSS
    神秘的 shadow-dom 浅析
    【CSS进阶】伪元素的妙用2
    【CSS进阶】CSS 颜色体系详解
    【CSS进阶】box-shadow 与 filter:drop-shadow 详解及奇技淫巧
  • 原文地址:https://www.cnblogs.com/Var123/p/5317876.html
Copyright © 2011-2022 走看看