ZOJ - 3195 Design the city
题目要对每次询问将一个树形图的三个点连接,输出最短距离。
利用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的更多相关文章
- zoj——3195 Design the city
Design the city Time Limit: 1 Second Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...
- zoj 3195 Design the city LCA Tarjan
题目链接 : ZOJ Problem Set - 3195 题目大意: 求三点之间的最短距离 思路: 有了两点之间的最短距离求法,不难得出: 对于三个点我们两两之间求最短距离 得到 d1 d2 d3 ...
- 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 ...
- ZOJ 3195 Design the city LCA转RMQ
题意:给定n个点,下面n-1行 u , v ,dis 表示一条无向边和边权值,这里给了一颗无向树 下面m表示m个询问,问 u v n 三点最短距离 典型的LCA转RMQ #include<std ...
- zoj 3195 Design the city lca倍增
题目链接 给一棵树, m个询问, 每个询问给出3个点, 求这三个点之间的最短距离. 其实就是两两之间的最短距离加起来除2. 倍增的lca模板 #include <iostream> #in ...
- ZOJ 3195 Design the city 题解
这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据 1 < N < 50000 1 < Q ...
- ZOJ Design the city LCA转RMQ
Design the city Time Limit: 1 Second Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...
- 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 ...
- xtu summer individual 1 C - Design the city
C - Design the city Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu D ...
随机推荐
- sql 复习
创建表 #设置外键 create table example3(id int primary key, stu_id int, course_id int, constraint c_fk forei ...
- SQL SERVER中的逻辑读,预读和物理读
sqlserver:数据存储方式:最小单位是页,每一页8k,sqlserver 对页的读取是具有原子性,也就是说,要么读取完整一页,要么完全不读取,不会有中间状态,而页之间的数据组织结构是B树 但是每 ...
- 在.net中设置debug模式预设代码
#region DEBUG #if DEBUG this.WorkOrgID.Value = "4DC4507E-434D-4EEB-967E-1E5CC28AA0C1"; thi ...
- Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行
Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...
- ###学习《Effective C++》
开源中国. #@date: 2014-06-16 #@author: gerui #@email: forgerui@gmail.com 前几天买了好几本书,其中有一本是<Effective C ...
- C语言:Day1~Day4
点击右键查看原图
- [GeekBand] C++学习笔记(2)——BigThree、OOP
本篇笔记主要分为三个部分,第一部分是以String类为例的基于对象的编程,重点在于构造与析构.拷贝构造函数.拷贝赋值函数三个重要函数.这一部分与笔记(1)中的内容结合起来就是基于对象编程的主要内容.第 ...
- mysql innodb 数据打捞(一)innodb 页面结构特征
如果文件系统损坏或意外删除了数据库文件,只要磁盘空间没有被覆盖,其实数据都还在磁盘的扇区中,还是可以恢复出来的,有些通用的文件恢复工具好象也可以恢复文件 ,但这里要研究的是在通用文件 恢复工具失效的时 ...
- LevelDb原理剖析
在说LevelDb之前,先认识两位大牛,Jeff Dean和Sanjay Ghemawat,这两位是Google公司重量级的工程师,为数甚少的Google Fellow之二. Jeff Dean其人: ...
- linux 源码安装软件原理
make 与 configure 在使用类似 gcc 的编译器来进行编译的过程并不简单,因为一套软件并不会仅有一支程序,而是有一堆程序码文件.所以除了每个主程序与副程序均需要写上一笔编译过程的命令外, ...