• bzoj2125 最短路


    Description

    给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

    Input

    输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问

    Output

    输出Q行,每行一个整数表示询问的答案

    Sample Input

    9 10 2
    1 2 1
    1 4 1
    3 4 1
    2 3 1
    3 7 1
    7 8 2
    7 9 2
    1 5 3
    1 6 4
    5 6 1
    1 9
    5 7

    Sample Output

    5
    6

    HINT

    对于100%的数据,N<=10000,Q<=10000

    http://immortalco.blog.uoj.ac/blog/1955

    基础概念这里不多说

    先求边双联通,建出圆方树

    dist[i]表示1到i的最短路,sum[i]表示从当前环的根到i的距离(不考虑另一个方向)

    len[cnt]表示编号为cnt的环的长度

    分3中情况:

    1.u,v的LCA是圆点,那么直接求dist[u]+dist[v]-2*dist[LCA]

    2.u,v的LCA是方点,但靠近LCA的两个祖先不属于同一个环,同上

    3.u,v的LCA是方点,但靠近LCA的两个祖先属于同一个环,设两个祖先为lca1,lca2

    那么答案就是dist[u]+dist[v]-dist[lca1]-dist[lca2]+环上最短路

    求lca1到lca2的环上最短路:s1=abs(sum[lca1]-sum[lca2])

                 s2=len[cnt]-s1

          min(s1,s2)

    所以第3种答案为ans+min(s1,s2)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<queue>
      7 using namespace std;
      8 typedef long long lol;
      9 struct Node
     10 {
     11   lol next,to;
     12   lol dis;
     13 }edge[500001];
     14 struct ZYYS
     15 {
     16   lol fr,to,dis;
     17 }sta[500001];
     18 lol head[200001],num,top;
     19 lol dist[200001],cntring,sum[200001],len[200001];
     20 lol belong[200001],fa[200001][21];
     21 lol dfn[200001],low[200001],cnt,dep[200001],n,m,q,tot;
     22 lol ans;
     23 bool vis[200001];
     24 void add(lol u,lol v,lol dis)
     25 {
     26   num++;
     27   edge[num].next=head[u];
     28   head[u]=num;
     29   edge[num].to=v;
     30   edge[num].dis=dis;
     31 }
     32 void SPFA()
     33 {lol i;
     34   queue<lol>Q;
     35   Q.push(1);
     36   memset(dist,127/3,sizeof(dist));
     37   memset(vis,0,sizeof(vis));
     38   dist[1]=0;
     39   while (Q.empty()==0)
     40     {
     41       lol u=Q.front();
     42       Q.pop();
     43       vis[u]=0;
     44       for (i=head[u];i;i=edge[i].next)
     45     {
     46       lol v=edge[i].to;
     47       if (dist[v]>dist[u]+edge[i].dis)
     48         {
     49           dist[v]=dist[u]+edge[i].dis;
     50           if (vis[v]==0)
     51         {
     52           Q.push(v);
     53           vis[v]=1;
     54         }
     55         }
     56     }
     57     }
     58 }
     59 void addring(lol u,lol v)
     60 {
     61   cntring++;
     62   while (sta[top].fr!=u&&sta[top].to!=v)
     63     {
     64       lol x=sta[top].fr,y=sta[top].to;
     65       lol d=sta[top--].dis;
     66       sum[x]=sum[y]+d;
     67       len[cntring]+=d;
     68       if (x!=u)
     69     {belong[x]=cntring;fa[x][0]=u;}
     70       if (y!=u)
     71     {belong[y]=cntring;fa[y][0]=u;}
     72     }
     73   lol x=sta[top].fr,y=sta[top].to;
     74   lol d=sta[top--].dis;
     75   sum[x]=sum[y]+d;
     76   len[cntring]+=d;
     77   fa[y][0]=x;
     78 }
     79 void tarjan(int now,int ff)
     80 {
     81      dfn[now]=low[now]=++tot;
     82      for(int i=head[now];i;i=edge[i].next)
     83       {
     84           int to=edge[i].to;
     85           if(to==ff)continue;
     86           if(!dfn[to])
     87            {
     88                 sta[++top]=(ZYYS){now,to,edge[i].dis};
     89                 tarjan(to,now);
     90                 low[now]=min(low[now],low[to]);
     91                 if(low[to]>=dfn[now])
     92                 {
     93                     addring(now,to);
     94                 }
     95             }else if(dfn[to]<low[now])low[now]=min(low[now],dfn[to]),sta[++top]=(ZYYS){now,to,edge[i].dis};
     96        }
     97 }
     98 void build(lol x,lol pa)
     99 {lol i;
    100   for (i=head[x];i;i=edge[i].next)
    101     {
    102       lol v=edge[i].to;
    103       if (v==pa) continue;
    104       dep[v]=dep[x]+1;
    105       build(v,x);
    106     }
    107 }
    108 lol LCA(lol x,lol y,lol &lca1,lol &lca2)
    109 {lol i;
    110   if (dep[x]<dep[y]) swap(x,y);
    111   lca1=y;lca2=y;
    112   lol ret=dist[x]+dist[y];
    113   for (i=20;i>=0;i--)
    114     if (dep[fa[x][i]]>=dep[y])
    115     {
    116       x=fa[x][i];
    117     }
    118   if (x==y) return ret-2*dist[lca1];
    119   for (i=20;i>=0;i--)
    120     if (fa[x][i]!=fa[y][i])
    121       x=fa[x][i],y=fa[y][i];
    122   lca1=x;lca2=y;
    123   return ret-2*dist[fa[x][0]];
    124 }
    125 int main()
    126 {
    127   lol i,u,v,j,lca1,lca2;
    128   lol d;
    129   cin>>n>>m>>q;
    130   for (i=1;i<=m;i++)
    131     {
    132       scanf("%lld%lld%lld",&u,&v,&d);
    133       add(u,v,d);add(v,u,d);
    134     }
    135   SPFA();
    136   tarjan(1,0);
    137   memset(head,0,sizeof(head));
    138   memset(edge,0,sizeof(edge));
    139   num=0;
    140   for (i=2;i<=n;i++)
    141     add(fa[i][0],i,0);
    142   for (i=1;i<=20;i++)
    143     for (j=1;j<=n;j++)
    144       fa[j][i]=fa[fa[j][i-1]][i-1];
    145   dep[1]=1;
    146   build(1,0);
    147   for (i=1;i<=q;i++)
    148     {
    149       scanf("%lld%lld",&u,&v);
    150       ans=LCA(u,v,lca1,lca2);
    151       if (belong[lca1]!=0&&belong[lca1]==belong[lca2])
    152       {
    153        ans=dist[u]+dist[v]-dist[lca1]-dist[lca2];
    154        lol s1=abs(sum[lca1]-sum[lca2]);
    155        lol s2=len[belong[lca1]]-s1;
    156        ans=ans+min(s1,s2);
    157       }
    158       printf("%lld
    ",ans);
    159     }
    160 }
  • 相关阅读:
    hh
    SDUT 3923 打字
    最短路
    阶乘后面0的个数(51Nod 1003)
    大数加法
    Biorhythms(中国剩余定理)
    usaco-5.1-theme-passed
    usaco-5.1-starry-passed
    usaco-5.1-fc-passed
    usaco-4.4-frameup-passed
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8190996.html
Copyright © 2020-2023  润新知