zoukankan      html  css  js  c++  java
  • hdu2874 LCA

    题意:现在有 n 个点与 m 条边的无向无环图,但是图不一定完全连通,边有各自的边权,给出多组询问,查询两点之间的路径权值和,或者输出两点不连通。

    一开始有最短路的想法,但是由于询问有 1e6 组,做单源最短路肯定会爆炸,而 1e4 的边数又觉得 floyd 时间空间都会炸,又因为是无环图,所以就想到了LCA的做法,大量询问让我很自然地就想到了离线Tarjan。由于不连通,就分多次Tarjan,通过标记来实现是否在同一棵树中。离线Tarjan 搞了一发结果就原来的做法估计是因为vector中的pair需要存问题编号或者是vector本身的原因,总之一直 MLE ,看了 discuss 有人提供了一种问题的存储方法,就是将所有问题也像链式前向星的方法存储,而节点编号分别是 0/1,2/3,这样的,只要用 节点编号/2 就能确定是哪个问题的结果。这样A掉了。但是不能忍的是我看见别人的题解里写的做法是直接递归向上爬LCA的做法……而且不是倍增!是一步一步爬的!递归!而且我交了一发还比离线快!这什么数据啊!卡空间不卡时间!暴力都能过!还更快!我不服!

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e4+1;
     5 const int maxm=2e4+1;
     6 const int maxq=1e6+1;
     7 
     8 int n;
     9 int head[maxn],nxt[maxm],point[maxm],val[maxm],size;
    10 int fa[maxn],dis[maxn];
    11 int vis1[maxn];
    12 int ans[maxq];
    13 int head1[maxn],point1[maxq<<1],nxt1[maxq<<1],size1;
    14 int cnt;
    15 
    16 void init(){
    17     memset(head,-1,sizeof(head));
    18     size=0;
    19     memset(head1,-1,sizeof(head1));
    20     size1=0;
    21     memset(vis1,0,sizeof(vis1));
    22     for(int i=1;i<=n;++i)fa[i]=i;
    23     memset(ans,-1,sizeof(ans));
    24     cnt=0;
    25 }
    26 
    27 void add(int a,int b,int v){
    28     point[size]=b;
    29     val[size]=v;
    30     nxt[size]=head[a];
    31     head[a]=size++;
    32     point[size]=a;
    33     val[size]=v;
    34     nxt[size]=head[b];
    35     head[b]=size++;
    36 }
    37 
    38 int find(int x){
    39     return x==fa[x]?x:fa[x]=find(fa[x]);
    40 }
    41 
    42 void Tarjan(int s,int pre){
    43     for(int i=head[s];~i;i=nxt[i]){
    44         int j=point[i];
    45         if(j!=pre){
    46             dis[j]=dis[s]+val[i];
    47             Tarjan(j,s);
    48             int x=find(j),y=find(s);
    49             if(x!=y)fa[x]=y;
    50         }
    51     }
    52     vis1[s]=cnt;
    53     for(int i=head1[s];~i;i=nxt1[i]){
    54         int j=point1[i];
    55         if(vis1[j]==vis1[s]){
    56             int lca=find(j);
    57             int id=i/2;
    58             ans[id]=dis[s]+dis[j]-2*dis[lca];
    59         }
    60     }
    61 }
    62 
    63 int main(){
    64     int m,k;
    65     while(scanf("%d%d%d",&n,&m,&k)!=EOF){
    66         init();
    67         while(m--){
    68             int a,b,v;
    69             scanf("%d%d%d",&a,&b,&v);
    70             add(a,b,v);
    71         }
    72         for(int i=0;i<k;++i){
    73             int a,b;
    74             scanf("%d%d",&a,&b);
    75             point1[size1]=b;
    76             nxt1[size1]=head1[a];
    77             head1[a]=size1++;
    78             point1[size1]=a;
    79             nxt1[size1]=head1[b];
    80             head1[b]=size1++;
    81         }
    82         for(int i=1;i<=n;++i){
    83             if(!vis1[i]){
    84                 ++cnt;
    85                 dis[i]=0;
    86                 Tarjan(i,0);
    87             }
    88         }
    89         for(int i=0;i<k;++i){
    90             if(ans[i]==-1)printf("Not connected
    ");
    91             else printf("%d
    ",ans[i]);
    92         }
    93     }
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    Binary Search Tree Iterator 解答
    Invert Binary Tree 解答
    Min Stack 解答
    Trapping Raining Water 解答
    Candy 解答
    Jump Game II 解答
    Implement Hash Map Using Primitive Types
    Gas Station 解答
    Bucket Sort
    HashMap 专题
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4829694.html
Copyright © 2011-2022 走看看