zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    eclipse修改web项目部署路径
    Jquery面试题
    23中设计模式之单例模式
    详细探讨单例模式
    java常用设计模式
    vue官网总结
    pytorch模型训练加速tricks
    element table显示滚动条
    vue中less文件全局引用
    vue路径别名无法识别,Cannot find module
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5118080.html
Copyright © 2011-2022 走看看