这个题目大意是:

    有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. Java面试12|Linux及Shell脚本

    1. 随便写一个awk的命令.用awk统计文本行数 (1)最近登录的5个帐号 last -n 5 | awk -F ':'(指定域分割符号) '{print $1}' 读入有'\n'换行符分割的一条记 ...

  2. Struts中数据处理

    对数据操作的3种方法(把数据保存到域中): 方式1:直接获取servletApi 核心类:ServletActionContext提供的静态方法 /** * 方式1:拿到servletApi,执行操作 ...

  3. ACM 比大小

    比大小 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 给你两个很大的数,你能不能判断出他们两个数的大小呢? 比如123456789123456789要大于-1234 ...

  4. 1297: [SCOI2009]迷路

    1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 652  Solved: 442[Submit][Status] ...

  5. 3732: Network

    3732: Network Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 395  Solved: 179[Submit][Status] Descr ...

  6. 从零开始学习Vue.js,学习笔记

    一.为什么学习vue.js methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节. vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn ...

  7. Jaro-Winkler Distance

    发现commons-lang 中有实现: StringUtils.class public static double getJaroWinklerDistance(final CharSequenc ...

  8. JavaScript 动态添加div 绑定点击事件

    1.动态添加div function cDiv(num){ var oDiv=document.createElement("div"); oDiv.className='divs ...

  9. HTML5学习笔记<一>: 认识H5

    什么是 HTML5? HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML 的上一个版本诞生于 1999 年.自从那以后,Web 世界已经经历了巨变. HTML5 仍 ...

  10. hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...