zoukankan      html  css  js  c++  java
  • HDU 2874 Connections between cities(LCA(离线、在线)求树上距离+森林)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874

    题目大意:给出n个点,m条边,q个询问,每次询问(u,v)的最短距离,若(u,v)不连通即不在同一颗树上则输出“Not connected”。

    解题思路:这题也是模板题,有所不同的是这次给出的是森林而不是一棵树,所以vis数组得稍作修改,标记vis数组的是当前树的编号。下面给出Tarjan和倍增法两种解法。

    Tarjan(离线)写法,被MLE坑了,离线写法必须要用静态邻接表,因为虽然n不大,但是q很大,所以如果存储问题邻接表会超内存。

    还有突然脑残把dis[x]+dis[y]-2*dis[lca(x,y)]写成dis[x]+dis[y]-dis[lca(x,y)]漏了个2看了半天!!!MDZZ!!!

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1e4+5;
     8 const int M=1e6+5;
     9 
    10 struct qnode{
    11     int to,id,next;
    12 }q[M*2];
    13 
    14 struct node{
    15     int to,w,next;
    16 }edge[N*2];
    17 
    18 int n,m,cnt,num,idx1,idx2;
    19 int res[M],root[N],vis[N],dis[N],head1[N],head2[N];
    20 
    21 void addedge(int u,int v,int w){
    22     edge[idx1].to=v;
    23     edge[idx1].w=w;
    24     edge[idx1].next=head1[u];
    25     head1[u]=idx1++;
    26 }
    27 
    28 void addq(int u,int v,int id){
    29     q[idx2].to=v;
    30     q[idx2].id=id;
    31     q[idx2].next=head2[u];
    32     head2[u]=idx2++;
    33 }
    34 
    35 int find(int x){
    36     return root[x]==x?x:root[x]=find(root[x]);
    37 }
    38 
    39 void init(){
    40     cnt=num=0;
    41     idx1=idx2=1;
    42     for(int i=1;i<=n;i++) root[i]=i;
    43     memset(res,-1,sizeof(res));
    44     memset(vis,0,sizeof(vis));
    45     memset(dis,0,sizeof(dis));
    46     memset(head1,0,sizeof(head1));
    47     memset(head2,0,sizeof(head2));
    48 }
    49 
    50 void lca(int u,int num){
    51     //注意这里vis[u]标记的是树的编号,为了判断点是否在同一颗树上
    52     vis[u]=num;
    53     //root[u]=u;
    54     for(int i=head1[u];i;i=edge[i].next){
    55         node t=edge[i];
    56         if(!vis[t.to]){
    57             dis[t.to]=dis[u]+t.w;
    58             lca(t.to,num);
    59             root[t.to]=u;
    60         }
    61     }
    62     for(int i=head2[u];i;i=q[i].next){
    63         qnode t=q[i];
    64         //属于同一颗树
    65         if(vis[t.to]==num)
    66             res[t.id]=dis[t.to]+dis[u]-2*dis[find(t.to)];
    67     }
    68 }
    69 
    70 int main(){
    71     int t;
    72     while(~scanf("%d%d%d",&n,&m,&t)){
    73         init();
    74         for(int i=1;i<=m;i++){
    75             int a,b,w;
    76             scanf("%d%d%d",&a,&b,&w);
    77             addedge(a,b,w);
    78             addedge(b,a,w);
    79         }
    80         for(int i=1;i<=t;i++){
    81             int a,b;
    82             scanf("%d%d",&a,&b);
    83             addq(a,b,i);
    84             addq(b,a,i);
    85         }
    86         //森林
    87         for(int i=1;i<=n;i++){
    88             if(!vis[i]) lca(i,i);
    89         }
    90         for(int i=1;i<=t;i++){
    91             if(res[i]==-1)
    92                 puts("Not connected");
    93             else
    94                 printf("%d
    ",res[i]);
    95         }
    96     }
    97     return 0;
    98 }

    倍增法(在线)写法,这个倒是不卡vector了,解决了上面所有问题后,我又脑残了的,我TM忘记调用bz()函数了!!!干瞪着瞪了两个小时两个小时啊!!!

    所以这道水题弄了我一个下午。。。。噗!

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1e5+5;
     8 
     9 struct node{
    10     int to,w;
    11     node(int to,int w):to(to),w(w){}
    12 };
    13 
    14 int n,m,q;
    15 int fa[N][31],depth[N],vis[N],dis[N];
    16 vector<node>v[N];
    17 
    18 void init(){
    19     for(int i=1;i<=n;i++) v[i].clear();
    20     memset(vis,0,sizeof(vis));
    21     memset(depth,0,sizeof(depth));
    22     memset(dis,0,sizeof(dis));
    23     memset(fa,0,sizeof(fa));
    24 }
    25 
    26 void dfs(int u,int num){
    27     vis[u]=num;
    28     for(int i=0;i<v[u].size();i++){
    29         node t=v[u][i];
    30         if(!vis[t.to]){
    31             depth[t.to]=depth[u]+1;
    32             fa[t.to][0]=u;
    33             dis[t.to]=dis[u]+t.w;
    34             dfs(t.to,num);
    35         }
    36     }
    37 }
    38 
    39 //倍增,处理fa数组
    40 void bz(){
    41     for(int j=1;j<=30;j++){
    42         for(int i=1;i<=n;i++){
    43             fa[i][j]=fa[fa[i][j-1]][j-1];
    44         }
    45     }
    46 }
    47 
    48 int lca(int x,int y){
    49     //保证深度大的点为x
    50     if(depth[x]<depth[y])
    51         swap(x,y);
    52     int dc=depth[x]-depth[y];
    53     for(int i=0;i<30;i++){
    54         if(1<<i&dc)                 //一个判断,模拟下就会清楚
    55             x=fa[x][i];
    56     }
    57     if(x==y)    return x;           //如果深度一样,两个点相同,直接返回
    58     for(int i=29;i>=0;i--){
    59         if(fa[x][i]!=fa[y][i]){     //跳2^i不一样,就跳,否则不跳
    60             x=fa[x][i];
    61             y=fa[y][i];
    62         }
    63     }
    64     return fa[x][0];
    65 }
    66 
    67 int main(){
    68     while(~scanf("%d%d%d",&n,&m,&q)){
    69         init();                     //初始化
    70         for(int i=1;i<=m;i++){
    71             int a,b,w;
    72             scanf("%d%d%d",&a,&b,&w);
    73             v[a].push_back(node(b,w));
    74             v[b].push_back(node(a,w));
    75         }
    76         for(int i=1;i<=n;i++){
    77             if(!vis[i]) dfs(i,i);
    78         }
    79         bz();                       //一定别忘了啊!!!
    80         for(int i=1;i<=q;i++){
    81             int x,y;
    82             scanf("%d%d",&x,&y);
    83             if(vis[x]!=vis[y])
    84                 puts("Not connected");
    85             else
    86                 printf("%d
    ",dis[x]+dis[y]-2*dis[lca(x,y)]);
    87         }
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    [extjs] ExtJs4.2 Form 表单提交
    [java ] java.util.zip.ZipException: error in opening zip file
    Oracle 11g 执行计划管理1
    Oracle 分区表的统计信息实例
    Oracle 手动收集统计信息
    Oracle 10g 之自动收集统计信息
    Oracle 11g 之自动收集统计信息
    Oracle 11gR2 RAC修改SCAN IP
    共享内存shared pool (6):追踪sql语句
    共享内存shared pool (5):详解一条SQL在library cache中解析
  • 原文地址:https://www.cnblogs.com/fu3638/p/8644784.html
Copyright © 2011-2022 走看看