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

利用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. sql 复习

    创建表 #设置外键 create table example3(id int primary key, stu_id int, course_id int, constraint c_fk forei ...

  2. SQL SERVER中的逻辑读,预读和物理读

    sqlserver:数据存储方式:最小单位是页,每一页8k,sqlserver 对页的读取是具有原子性,也就是说,要么读取完整一页,要么完全不读取,不会有中间状态,而页之间的数据组织结构是B树 但是每 ...

  3. 在.net中设置debug模式预设代码

    #region DEBUG #if DEBUG this.WorkOrgID.Value = "4DC4507E-434D-4EEB-967E-1E5CC28AA0C1"; thi ...

  4. Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行

    Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...

  5. ###学习《Effective C++》

    开源中国. #@date: 2014-06-16 #@author: gerui #@email: forgerui@gmail.com 前几天买了好几本书,其中有一本是<Effective C ...

  6. C语言:Day1~Day4

    点击右键查看原图

  7. [GeekBand] C++学习笔记(2)——BigThree、OOP

    本篇笔记主要分为三个部分,第一部分是以String类为例的基于对象的编程,重点在于构造与析构.拷贝构造函数.拷贝赋值函数三个重要函数.这一部分与笔记(1)中的内容结合起来就是基于对象编程的主要内容.第 ...

  8. mysql innodb 数据打捞(一)innodb 页面结构特征

    如果文件系统损坏或意外删除了数据库文件,只要磁盘空间没有被覆盖,其实数据都还在磁盘的扇区中,还是可以恢复出来的,有些通用的文件恢复工具好象也可以恢复文件 ,但这里要研究的是在通用文件 恢复工具失效的时 ...

  9. LevelDb原理剖析

    在说LevelDb之前,先认识两位大牛,Jeff Dean和Sanjay Ghemawat,这两位是Google公司重量级的工程师,为数甚少的Google Fellow之二. Jeff Dean其人: ...

  10. linux 源码安装软件原理

    make 与 configure 在使用类似 gcc 的编译器来进行编译的过程并不简单,因为一套软件并不会仅有一支程序,而是有一堆程序码文件.所以除了每个主程序与副程序均需要写上一笔编译过程的命令外, ...