这个题目大意是:

    有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)]

    代码如下:

    

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 200010
#define M 600010
using namespace std;
struct DATA
{
int from,to,dis,next,i;
}road[N],ques[M];
int dist[N],head1[N],head2[M],f[N],ans[M],n,q,len1,len2,fun=;
bool vis[N],book[M],found[N];
void add1(int a,int b,int c,int i)
{
len1++;
road[len1].from=a;
road[len1].to=b;
road[len1].dis=c;
road[len1].i=i;
road[len1].next=head1[a];
head1[a]=len1;
}
void add2(int a,int b,int c,int i)
{
len2++;
ques[len2].from=a;
ques[len2].to=b;
ques[len2].dis=c;
ques[len2].i=i;
ques[len2].next=head2[a];
head2[a]=len2;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void marge(int x,int y){if(find(x)!=find(y)) f[y]=x;}
void Tarjan(int u,int dev)
{
int e=head1[u],a,b,i,tmp;
while(e!=-)
{
a=road[e].to;
i=road[e].i;
tmp=dev+road[e].dis;
if(!vis[a] && !found[i])
{
found[i]=;
dist[a]=tmp;
Tarjan(a,tmp);
vis[a]=;
marge(u,a);
}
e=road[e].next;
}
e=head2[u];
while(e!=-)
{
a=ques[e].to;
i=ques[e].i;
if(vis[a] && !book[i])
{
book[i]=;
b=find(a);
ans[i]=dist[a]+dist[u]-*dist[b];
}
e=ques[e].next;
}
return ;
}
void init()
{
int i;
len1=,len2=;
for(i=;i<N;i++)
{
road[i].from=road[i].to=road[i].dis=road[i].next=road[i].i=;
f[i]=i;
}
for(i=;i<M;i++)
ques[i].from=ques[i].to=ques[i].dis=ques[i].next=ques[i].i=;
memset(head1,-,sizeof(head1));
memset(head2,-,sizeof(head2));
memset(dist,,sizeof(dist));
memset(vis,,sizeof(vis));
memset(book,,sizeof(book));
memset(found,,sizeof(found));
memset(ans,,sizeof(ans));
return ;
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("test.out","w",stdout);
while(~scanf("%d",&n))
{
if(fun++) printf("\n");
init();
int i,a,b,c,tmp=;
for(i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
add1(a,b,c,i);
add1(b,a,c,i);
tmp=min(min(a,b),tmp);
}
scanf("%d",&q);
for(i=;i<=q;i++)
{
scanf("%d%d%d",&a,&b,&c);
add2(a,b,,i);
add2(b,a,,i);
add2(a,c,,i+q);
add2(c,a,,i+q);
add2(b,c,,i+*q);
add2(c,b,,i+*q);
}
Tarjan(tmp,);
for(i=;i<=q;i++)
printf("%d\n",(ans[i]+ans[i+q]+ans[i+*q])/);
}
return ;
}

ZOJ 3195 Design the city 题解的更多相关文章

  1. zoj——3195 Design the city

    Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...

  2. ZOJ 3195 Design the city (LCA 模板题)

    Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terribl ...

  3. zoj 3195 Design the city LCA Tarjan

    题目链接 : ZOJ Problem Set - 3195 题目大意: 求三点之间的最短距离 思路: 有了两点之间的最短距离求法,不难得出: 对于三个点我们两两之间求最短距离 得到 d1 d2 d3 ...

  4. ZOJ 3195 Design the city LCA转RMQ

    题意:给定n个点,下面n-1行 u , v ,dis 表示一条无向边和边权值,这里给了一颗无向树 下面m表示m个询问,问 u v n 三点最短距离 典型的LCA转RMQ #include<std ...

  5. ZOJ - 3195 Design the city

    题目要对每次询问将一个树形图的三个点连接,输出最短距离. 利用tarjan离线算法,算出每次询问的任意两个点的最短公共祖先,并在dfs过程中求出离根的距离.把每次询问的三个点两两求出最短距离,这样最终 ...

  6. zoj 3195 Design the city lca倍增

    题目链接 给一棵树, m个询问, 每个询问给出3个点, 求这三个点之间的最短距离. 其实就是两两之间的最短距离加起来除2. 倍增的lca模板 #include <iostream> #in ...

  7. ZOJ Design the city LCA转RMQ

    Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...

  8. ZOJ3195 Design the city [2017年6月计划 树上问题04]

    Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...

  9. xtu summer individual 1 C - Design the city

    C - Design the city Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu D ...

随机推荐

  1. Linux usb子系统(一) _写一个usb鼠标驱动

    USB总线是一种典型的热插拔的总线标准,由于其优异的性能几乎成为了当下大小设备中的标配. USB的驱动可以分为3类:SoC的USB控制器的驱动,主机端USB设备的驱动,设备上的USB Gadget驱动 ...

  2. 关于label和input对齐的那些事

    input文本和label对齐 默认状态下,也就是下面这样, 文字和input是居中的. <div> <label>我是中国人</label> <input ...

  3. Objective-c日记-之属性列表

    属性列表 1,概述 在Cocoa中,有一类名为属性列表的对象(常简写为plist),Cocoa知道如何将它们保存到文件和从文件中加载.包括以下类NSArray,NSDictionary,NSStrin ...

  4. wemall doraemon中Android app商城系统向指定URL发送GET方法的请求代码

    URL的openConnection()方法将返回一个URLConnection对象,该对象表示应用程序和 URL 之间的通信链接.程序可以通过URLConnection实例向该URL发送请求.读取U ...

  5. MSTP多实例的配置

    MSTP多实例的配置 这次实验主要是为了加强对stp生成树协议中,RP(根端口),DP(指定端口),AP(阻塞端口)的判断方法:虽然很多时候不需要我们人工判断,因为当我们吧所有的配置好之后,然后开启生 ...

  6. fprintf&prinft&sprintf

    1: fprintf()#include <stdio.h> int fprintf( FILE *stream, const char *format, ... );fprintf()函 ...

  7. HTML5初步了解

        一.使用HTML5的十大原因 你难道还没有考虑使用HTML5? 当然我猜想你可能有自己的原因:它现在还没有被广泛的支持,在IE中不好使,或者你就是喜欢写比较严格的XHTML代码.HTML5是w ...

  8. scanf函数之扫描集

    前言 %[]是scanf函数不常用到的格式字符--扫描集(scanset),它的用法很简单,但却能巧妙地解决一些输入问题.(由于书籍里和网上对此格式字符的介绍很少且篇幅较小,本文可能会有些许错误,请读 ...

  9. JavaWeb之JSP技术总结

    刚接触JSP技术的时候让我想起了在大学学的Asp+VBScript,记得当时我还用aspstudy做了一个小的新闻发布系统作为期末作品,也正是在那时候在卢哥卢老师的指导下走向编程的道路,对编程越来越感 ...

  10. 关于ORACLE通过file_id与block_id定位数据库对象遇到的问题的一点思考

    在ORACLE中,我们可以通过file_id(file#)与block_id(block#)去定位一个数据库对象(object).例如,我们在10046生成的trace文件中file#=4 block ...