题目要对每次询问将一个树形图的三个点连接,输出最短距离。

利用tarjan离线算法,算出每次询问的任意两个点的最短公共祖先,并在dfs过程中求出离根的距离。把每次询问的三个点两两求出最短距离,这样最终结果就是3个值一半。

其实开始我用的一种很挫的方法才AC的,具体思路就不说了,感觉很麻烦又不好写的样子。怎么没想到上面的简便方法呢。

初始代码:

 #include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mp(a, b) make_pair((a), (b))
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii> VII;
typedef vector<pii, int> VIII;
typedef VI:: iterator IT;
const int maxn = + ;
const int maxm = ( + ) * ;
int dis[maxn], lin[maxm][], vis[maxn], pa[maxn];
VII g[maxn];
VII query[maxn];
int n, m;
int findset(int x)
{
return pa[x] == x? x : pa[x] = findset(pa[x]);
}
void tarjan(int u)
{
vis[u] = ;
pa[u] = u;
for(int i = ; i < (int)query[u].size(); i++)
{
int v= query[u][i].first;
if(vis[v])
{
lin[query[u][i].second][] = findset(v);
}
}
for(int i = ; i < (int)g[u].size(); i++)
{
int v = g[u][i].second;
if(!vis[v])
{
dis[v] = dis[u] + g[u][i].first;
tarjan(v);
pa[v] = u;
}
}
}
void Init(void)
{
for(int i = ; i < maxn; i++)
query[i].clear(), g[i].clear();
memset(vis, , sizeof(vis));
}
int main(void)
{
int flag = ;
while(scanf("%d", &n) == )
{
if(flag) puts("");
else flag = ;
Init();
for(int i = ; i < n; i++)
{
int u, v, len;
scanf("%d%d%d", &u, &v, &len);
g[u].pb(mp(len, v));
g[v].pb(mp(len, u));
}
scanf("%d", &m);
for(int i = ; i <= *m; i += )
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
query[lin[i][] = x].pb(mp(lin[i][] = y, i));
query[lin[i][]].pb(mp(lin[i][], i));
query[lin[i+][] = x].pb(mp(lin[i+][] = z, i+));
query[lin[i+][]].pb(mp(lin[i+][], i+));
query[lin[i+][] = y].pb(mp(lin[i+][] = z, i+));
query[lin[i+][]].pb(mp(lin[i+][], i+));
}
dis[] = ;
tarjan();
for(int i = ; i <= *m; i += )
{
int ans;
if(lin[i+][] == lin[i+][])
{
// if(lin[i+2][2] == 0)
// ans = dis[lin[i][0]] + dis[lin[i][1]] - 2 * dis[lin[i][2]] + dis[lin[i][2]] + dis[lin[i+1][1]];
ans = dis[lin[i][]] + dis[lin[i][]] - * dis[lin[i][]] - *dis[lin[i+][]] + dis[lin[i+][]] + dis[lin[i][]];
}
else
ans = dis[lin[i][]] + dis[lin[i][]] - * dis[lin[i][]] + dis[lin[i+][]]- max(dis[lin[i+][]], dis[lin[i+][]]);
printf("%d\n",ans);
}
}
return ;
}

简便方法的代码:

 #include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mp(a, b) make_pair((a), (b))
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii> VII;
typedef vector<pii, int> VIII;
typedef VI:: iterator IT;
const int maxn = + ;
const int maxm = ( + ) * ;
int dis[maxn], lin[maxm][], vis[maxn], pa[maxn];
VII g[maxn];
VII query[maxn];
int ans[maxm];
int n, m;
int findset(int x)
{
return pa[x] == x? x : pa[x] = findset(pa[x]);
}
void tarjan(int u)
{
vis[u] = ;
pa[u] = u;
for(int i = ; i < (int)query[u].size(); i++)
{
int v= query[u][i].first;
if(vis[v])
{
ans[query[u][i].second] += dis[u] + dis[v] - * dis[findset(v)];
}
}
for(int i = ; i < (int)g[u].size(); i++)
{
int v = g[u][i].second;
if(!vis[v])
{
dis[v] = dis[u] + g[u][i].first;
tarjan(v);
pa[v] = u;
}
}
}
void Init(void)
{
for(int i = ; i < maxn; i++)
query[i].clear(), g[i].clear();
memset(vis, , sizeof(vis));
memset(ans, , sizeof(ans));
}
int main(void)
{
int flag = ;
while(scanf("%d", &n) == )
{
if(flag) puts("");
else flag = ;
Init();
for(int i = ; i < n; i++)
{
int u, v, len;
scanf("%d%d%d", &u, &v, &len);
g[u].pb(mp(len, v));
g[v].pb(mp(len, u));
}
scanf("%d", &m);
for(int i = ; i <= m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
query[x].pb(mp(y, i));
query[y].pb(mp(x, i));
query[x].pb(mp(z, i));
query[z].pb(mp(x, i));
query[y].pb(mp(z, i));
query[z].pb(mp(y, i));
}
dis[] = ;
tarjan();
for(int i = ; i <= m; i++)
{
printf("%d\n", ans[i]>>);
}
}
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 Tarjan

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

  3. 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 ...

  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 lca倍增

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

  6. ZOJ 3195 Design the city 题解

    这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据  1 < N < 50000  1 < Q ...

  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. hasLayout与Block formatting contexts的学习(下)

    BFC布局规则: 内部的Box会在垂直方向,一个接一个地放置. Box垂直方向的距离由margin决定.属于同一个BFC的两个相邻Box的margin会发生重叠 每个元素的margin box的左边, ...

  2. WEB前端优化一些经验技巧

    引言: 1. 慢的页面可能会网站失去更多的用户. 2. 慢500ms意味着20%的用户将放弃访问(google) 3. 慢100ms意味着1%的用户将放弃交易(amazon) 前段时间偶然看到网上的两 ...

  3. .Net程序跑在Linux上

    .Net越来越拥抱开源了,今天就试了如何让.Net程序跑在Linux上,果然再无人可以阻挡.Net的脚步了. Linux Disibutaion:Open Logic 7.2 1.Install .N ...

  4. 如何入侵Linux操作系统

    我发现了一个网站,于是常规入侵.很好,它的FINGER开着,于是我编了一个SHELL,aaa帐号试到zzz(by the way,这是我发现的一个网上规律,那就是帐号的长度与口令的强度成正比, 如果一 ...

  5. JavaScript学习笔记(5)——JavaScript语法之数据类型

    JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: var x // x 为 undefined var x = 6; // x 为数字 var x = "Bill&q ...

  6. Wix: Show conditional message box

    For example: Scenario: Show message box only during installation and MYPROPERTY has to be equal to & ...

  7. Build Error 6041: Internal build error

    Note: Following content is reprinted from the Original article Flexera : Build Error 6041. Only for ...

  8. STL的简介

    Standard Template Library,(标准模板库)<来自百度百科的整理> ————可复用性(reusability) STL是基于模板,内联函数的使用使得生成的代码短小高效 ...

  9. Java 与 Python 的对比

    最近在学习Python, 现在写一个Python程序和Java程序进行对一下比,以此展示各自不同的特点.这个程序的功能是计算([n, m) )之间的闰年.     Python程序如下: def fu ...

  10. Nginx+keepalived实现负载均衡

    Nginx的优点是: 1.工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名.目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx ...