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\n",ans);
159     }
160 }

 

posted @ 2018-01-04 07:57  Z-Y-Y-S  阅读(...)  评论(...编辑  收藏