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

利用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. 正则表达式 自学笔记整理记录 EASY REGEX~

    整理正则表达式篇                             -wuian7yulian 基础知识介绍 :  1> 字符串的组成: 对于字符串"ABC"来说,其包 ...

  2. oracle两种导出导入方式,即imp与impdp之比较

    尽管使用了很多次impexp及impdpexpdp但是使用起来还是会遇到很多问题,现总结如下: 应用:将一个用户的所有表结构及索引,触发器,过程,函数等导入到另一用户里 imp/exp 导出用户表结构 ...

  3. 也谈一下Activiti工作流节点的自由跳转

    最近在搞openwebflow的工作流节点自由跳转功能,在网上看了一些资料,感觉不是很好,总结原因如下: 直接手动调用SqlSession的操作,感觉会漏掉一些重要的初始化操作(如:启动新节点之后加载 ...

  4. jenkins离线安装git插件

    jenkins没有默认安装git,当jenkins无法连接外网的话,安装git插件就是一件很麻烦的事,需要自己去下载插件: 往下拉 这边的插件就是需要自己去下载了,在bing下搜索jenkins gi ...

  5. Invalid result location value/parameter

    Invalid result location value/parameter(struts2),该问题在myeclipse8.6一下的版本不会出现,但是在myeclipse9.0中就会出现该错误.有 ...

  6. mysql net连接读取结果为乱码 Incorrect string value

    在mysql直接查询中文正常,通过连接到mysql读取中文内容为乱码.同时插入中文内容也失败提示 Incorrect string value: '\xBC\xA4\xB7\xA2\xBF\xB4.. ...

  7. poj3190 stall revertation

                                                                                                Stall Re ...

  8. Oracle外部表详解(转载)

    (外部表创建主要注意创建目录访问权限问题.目录路径格式无空格等不相关字符,即必须是当前表访问用户可以访问:关于表中行数的限制问题,如果不加限制注意添加reject limit unlimited:表中 ...

  9. Javascript访问css样式信息

    DOM2级样式为style对象定义了一些属性和方法,可以通过这些方法属性来访问或者修改元素的样式信息: 1.cssText:可读写,在读的情况下以字符串形式返回元素的css代码,在写的情况下以字符串形 ...

  10. Linux下简易蜂鸣器驱动代码及测试实例

    驱动代码: #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> ...