• ZOJ 3195 Design the city 题解


        这个题目大意是:

        有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值。

        多组数据 每组数据  1 < N < 50000  1 < Q < 70000;

        一道多源最短路的题目,注意题目数据:N、Q都很大

        不能考虑Floyd、SPFA、Dijkstra、Bellman-Ford等最短路算法

        再看N-1条边,明显构成一棵树,最短路有且只有一条

        很明显需要LCA....

        不懂LCA的点!我!点!我

        我们所熟知的LCA是求两个点的最短路,而该题稍微变形,要求三个点

        所以我们可以两两求LCA,然后把三个dist值加起来除以二

        而两点的dist值是这样算的:dist[a]+dist[b]-2*dist[LCA(a,b)]

        代码如下:

        

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define N 200010
      6 #define M 600010
      7 using namespace std;
      8 struct DATA
      9 {
     10     int from,to,dis,next,i;
     11 }road[N],ques[M];
     12 int dist[N],head1[N],head2[M],f[N],ans[M],n,q,len1,len2,fun=0;
     13 bool vis[N],book[M],found[N];
     14 void add1(int a,int b,int c,int i)
     15 {
     16     len1++;
     17     road[len1].from=a;
     18     road[len1].to=b;
     19     road[len1].dis=c;
     20     road[len1].i=i;
     21     road[len1].next=head1[a];
     22     head1[a]=len1;
     23 }
     24 void add2(int a,int b,int c,int i)
     25 {
     26     len2++;
     27     ques[len2].from=a;
     28     ques[len2].to=b;
     29     ques[len2].dis=c;
     30     ques[len2].i=i;
     31     ques[len2].next=head2[a];
     32     head2[a]=len2;
     33 }
     34 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
     35 void marge(int x,int y){if(find(x)!=find(y)) f[y]=x;}
     36 void Tarjan(int u,int dev)
     37 {
     38     int e=head1[u],a,b,i,tmp;
     39     while(e!=-1)
     40     {
     41         a=road[e].to;
     42         i=road[e].i;
     43         tmp=dev+road[e].dis;
     44         if(!vis[a] && !found[i])
     45         {
     46             found[i]=1;
     47             dist[a]=tmp;
     48             Tarjan(a,tmp);
     49             vis[a]=1;
     50             marge(u,a);
     51         }
     52         e=road[e].next;
     53     }
     54     e=head2[u];
     55     while(e!=-1)
     56     {
     57         a=ques[e].to;
     58         i=ques[e].i;
     59         if(vis[a] && !book[i])
     60         {
     61             book[i]=1;
     62             b=find(a);
     63             ans[i]=dist[a]+dist[u]-2*dist[b];
     64         }
     65         e=ques[e].next;
     66     }
     67     return ;
     68 }
     69 void init()
     70 {
     71     int i;
     72     len1=0,len2=0;
     73     for(i=0;i<N;i++)
     74     {
     75         road[i].from=road[i].to=road[i].dis=road[i].next=road[i].i=0;
     76         f[i]=i;
     77     }
     78     for(i=0;i<M;i++)
     79         ques[i].from=ques[i].to=ques[i].dis=ques[i].next=ques[i].i=0;
     80     memset(head1,-1,sizeof(head1));
     81     memset(head2,-1,sizeof(head2));
     82     memset(dist,0,sizeof(dist));
     83     memset(vis,0,sizeof(vis));
     84     memset(book,0,sizeof(book));
     85     memset(found,0,sizeof(found));
     86     memset(ans,0,sizeof(ans));
     87     return ;
     88 }
     89 int main()
     90 {
     91 //    freopen("1.in","r",stdin);
     92 //    freopen("test.out","w",stdout);
     93     while(~scanf("%d",&n))
     94     {
     95         if(fun++) printf("
    ");
     96         init();
     97         int i,a,b,c,tmp=99999999;
     98         for(i=1;i<n;i++)
     99         {
    100             scanf("%d%d%d",&a,&b,&c);
    101             add1(a,b,c,i);
    102             add1(b,a,c,i);
    103             tmp=min(min(a,b),tmp);
    104         }
    105         scanf("%d",&q);
    106         for(i=1;i<=q;i++)
    107         {
    108             scanf("%d%d%d",&a,&b,&c);
    109             add2(a,b,0,i);
    110             add2(b,a,0,i);
    111             add2(a,c,0,i+q);
    112             add2(c,a,0,i+q);
    113             add2(b,c,0,i+2*q);
    114             add2(c,b,0,i+2*q);
    115         }
    116         Tarjan(tmp,0);
    117         for(i=1;i<=q;i++)
    118             printf("%d
    ",(ans[i]+ans[i+q]+ans[i+2*q])/2);
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    使用windows自带工具计算文件 MD5 值
    去除桌面图标的箭头
    给自己电脑(物理机)安装 linux 系统
    Python 字典 fromkeys()方法的坑
    Python 超时(运行时间太长) 自定义多长时间结束进程
    Win10 python2和python3共存
    verdidebussy的使用技巧
    <DC guide ---2>
    <DC guide ---1>
    <RTL To GDS ---第一阶段>
  • 原文地址:https://www.cnblogs.com/JVxie/p/4933535.html
Copyright © 2020-2023  润新知