bzoj3047: Freda的传呼机 && 2125: 最短路

Description

为了随时与rainbow快速交流,Freda制造了两部传呼机。Freda和rainbow所在的地方有N座房屋、M条双向光缆。每条光缆连接两座房屋,传呼机发出的信号只能沿着光缆传递,并且传呼机的信号从光缆的其中一端传递到另一端需要花费t单位时间。现在Freda要进行Q次试验,每次选取两座房屋,并想知道传呼机的信号在这两座房屋之间传递至少需要多长时间。Freda和rainbow简直弱爆了有木有T_T,请你帮帮他们吧……
N座房屋通过光缆一定是连通的,并且这M条光缆有以下三类连接情况:
A:光缆不形成环,也就是光缆仅有N-1条。
B:光缆只形成一个环,也就是光缆仅有N条。
C:每条光缆仅在一个环中。。

Input

第一行包含三个用空格隔开的整数,N、M和Q。
接下来M行每行三个整数x、y、t,表示房屋x和y之间有一条传递时间为t的光缆。
最后Q行每行两个整数x、y,表示Freda想知道在x和y之间传呼最少需要多长时间。

Output

输出Q行,每行一个整数,表示Freda每次试验的结果。

Sample Input

样例输入1
5 4 2
1 2 1
1 3 1
2 4 1
2 5 1
3 5
2 1

样例输入2
5 5 2
1 2 1
2 1 1
1 3 1
2 4 1
2 5 1
3 5
2 1

样例输入3
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



样例输出1
3
1

样例输出2
3
1

样例输出3
5
6

HINT

对于100%的数据,2<=N<=10000,N-1<=M<=12000,Q=10000,1<=x,y<=N,1<=t<32768

题解:

其实这三种情况都是仙人掌。。。

先重新建图,将原图中的一个点双(其实就是环)缩成一个点,如果一个点属于多个点双,则这个点向每个点双连条边,还有原图的桥边也要在新图里

由于这是仙人掌,得到的新图一定是个树,然后就想树上的最短路一样的求lca

不过要分清况讨论只有一个点是lca,两个点都是lca,两个点都不是lca,lca是环还是点等等,反正比较复杂

(感觉还是没讲清,看代码吧。。。)

code:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<vector>
  5 #include<cstring>
  6 #include<algorithm>
  7 #define maxn 20005
  8 #define maxm maxn<<2
  9 #define mod 236897
 10 using namespace std;
 11 typedef long long int64;
 12 char ch;
 13 bool ok;
 14 void read(int &x){
 15     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
 16     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
 17     if (ok) x=-x;
 18 }
 19 int n,m,q,a,b,c;
 20 int idx,dfn[maxn],low[maxn];
 21 int top,cnt,bnm[maxn],tmp[maxn];
 22 struct Stack{
 23     int id,val;
 24 }stack[maxn];
 25 struct Point{
 26     vector<int> bel,pos;
 27     int siz;
 28     void init(int a,int b){siz++,bel.push_back(a),pos.push_back(b);}
 29 }point[maxn];
 30 struct SCC{
 31     vector<int> id,dis;
 32     int siz,len,head;
 33     void add(int v,int d){siz++,id.push_back(v),dis.push_back(d);}
 34     int query(int a,int b){
 35         int tmp=abs(dis[a]-dis[b]);
 36         return min(tmp,len-tmp);
 37     }
 38 }scc[maxn];
 39 int fa[maxn][15],dep[maxn],dis[maxn];
 40 struct Hash{
 41     int tot,key[mod],pre[maxn],ans[maxn];
 42     int64 val[maxn];
 43     void add(int a,int b,int id){
 44         int64 t=1LL*a*maxn+b;
 45         int u=t%mod;
 46         for (int p=key[u];p;p=pre[p]) if (val[p]==t) return;
 47         pre[++tot]=key[u],key[u]=tot,ans[tot]=id,val[tot]=t;
 48     }
 49     int find(int a,int b){
 50         int64 t=1LL*a*maxn+b;
 51         int u=t%mod;
 52         for (int p=key[u];p;p=pre[p]) if (val[p]==t) return ans[p];
 53         return -1;
 54     }
 55 }hash;
 56 int num;
 57 struct Edge{
 58     int a,b,c;
 59 }edge[maxm];
 60 struct Graph{
 61     int tot,now[maxn],son[maxm],pre[maxm],val[maxm];
 62     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
 63     void add(int a,int b,int c){put(a,b,c),put(b,a,c);}
 64     void dfs(int u,int fa,int va){
 65         dfn[u]=low[u]=++idx,stack[++top]=(Stack){u,va};
 66         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
 67             if (!dfn[v]) dfs(v,u,val[p]),low[u]=min(low[u],low[v]);
 68             else if (v!=fa) tmp[u]=val[p],low[u]=min(low[u],dfn[v]);
 69         if (dfn[u]==low[u]){
 70             top--;
 71             if (fa) bnm[u]++,bnm[fa]++,edge[++num]=(Edge){fa,u,va};
 72         }
 73         if (low[u]==dfn[fa]){
 74             int v,va,d=0,id=0,first=stack[top].id; ++cnt;
 75             do{
 76                 v=stack[top].id,va=stack[top].val,top--;
 77                 point[v].init(cnt,id++),scc[cnt].add(v,d),d+=va;
 78             }while (v!=u);
 79             point[fa].init(cnt,id++),scc[cnt].add(fa,d),scc[cnt].len=d+tmp[first];
 80         }
 81     }
 82     void dfs1(int u){
 83         for (int i=0;fa[u][i];i++) fa[u][i+1]=fa[fa[u][i]][i];
 84         if (u>n){
 85             int idx=u-n;
 86             if (fa[u][0]) scc[idx].head=hash.find(fa[u][0],idx);
 87             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
 88                 if (v!=fa[u][0]){
 89                     fa[v][0]=u,dep[v]=dep[u]+1;
 90                     dis[v]=dis[u]+scc[idx].query(scc[idx].head,hash.find(v,idx)),dfs1(v);
 91                 }
 92         }
 93         else for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
 94             if (v!=fa[u][0]) fa[v][0]=u,dep[v]=dep[u]+1,dis[v]=dis[u]+val[p],dfs1(v);
 95     }
 96 }G1,G2;
 97 void swim(int &u,int h){for (int i=14;h;i--) if (h>=(1<<i)) h-=(1<<i),u=fa[u][i];}
 98 int get_lca(int u,int v){
 99     if (dep[u]<dep[v]) swap(u,v);
100     swim(u,dep[u]-dep[v]);
101     if (u==v) return u;
102     for (int i=14;i>=0;i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
103     return fa[u][0];
104 }
105 int get(int u){
106     if (!point[u].siz) return u;
107     return point[u].bel[0]+n;
108 }
109 void query(int a,int b){
110     int ans=0;
111     int ta=get(a),tb=get(b);
112     int lca=get_lca(ta,tb);
113     if (tb==lca) swap(ta,tb),swap(a,b);
114     if (ta==lca){
115         if (tb==lca){
116             if (lca>n){
117                 int ida=hash.find(a,lca-n),idb=hash.find(b,lca-n);
118                 printf("%d
",scc[lca-n].query(ida,idb));
119             }
120             else puts("0");
121         }
122         else{
123             if (tb>n) ans+=scc[tb-n].query(scc[tb-n].head,point[b].pos[0]),b=tb;
124             if (lca>n){
125                 swim(tb,dep[tb]-dep[lca]-1);
126                 int ida=hash.find(a,lca-n),idb=hash.find(tb,lca-n);
127                 printf("%d
",ans+dis[b]-dis[tb]+scc[lca-n].query(ida,idb));
128             }
129             else printf("%d
",ans+dis[tb]-dis[lca]);
130         }
131     }
132     else{
133         if (ta>n) ans+=scc[ta-n].query(scc[ta-n].head,point[a].pos[0]),a=ta;
134         if (tb>n) ans+=scc[tb-n].query(scc[tb-n].head,point[b].pos[0]),b=tb;
135         if (lca>n){
136             swim(ta,dep[ta]-dep[lca]-1),swim(tb,dep[tb]-dep[lca]-1);
137             int ida=hash.find(ta,lca-n),idb=hash.find(tb,lca-n);
138             printf("%d
",ans+dis[a]-dis[ta]+dis[b]-dis[tb]+scc[lca-n].query(ida,idb));
139         }
140         else printf("%d
",ans+dis[a]+dis[b]-(dis[lca]<<1));
141     }
142 }
143 int main(){
144     read(n),read(m),read(q);
145     for (int i=1;i<=m;i++) read(a),read(b),read(c),G1.add(a,b,c);
146     for (int i=1;i<=n;i++) if (!dfn[i]) G1.dfs(i,0,0);
147     for (int i=1;i<=num;i++) G2.add(edge[i].a,edge[i].b,edge[i].c);
148     for (int u=1;u<=n;u++) if (bnm[u]+point[u].siz>=2)
149         for (int i=0;i<point[u].siz;i++) G2.add(u,n+point[u].bel[i],0);
150     for (int u=1;u<=n;u++) for (int i=0;i<point[u].siz;i++) hash.add(u,point[u].bel[i],point[u].pos[i]);
151     int root=cnt?n+1:1;
152     G2.dfs1(root);
153     while (q--) read(a),read(b),query(a,b);
154     return 0;
155 }
原文地址:https://www.cnblogs.com/chenyushuo/p/5118080.html