↓ 跳过正文
  1. Posts/

hdu 2586 How far away ? (tarjan算法求LCA模板题)

·856 字·2 分钟

题目链接 题意:一棵树,给出n-1个边权,然后q组查询,每组查询询问两个点之间的距离。 思路:

dfs跑出根到每个点的距离,设为dis[i] 那么u,v两点的距离就是ans = dis[u]+dis[v]-2*dis[lca(u,v)];

其中lca(u,v)为u,v的最近公共祖先。 这个式子是利用容斥,其实也很直观。。不理解的话画个图就好。

所以终点就是求两个点的LCA.

据说有好多种做法。今天学习了大概是最简单的一种? 学习链接

 1//parent为并查集,FIND为并查集的查找操作
 2//QUERY为询问结点对集合
 3//TREE为基图有根树
 4 Tarjan(u)
 5      visit[u] = true
 6      for each (u, v) in TREE
 7          if !visit[v]
 8              Tarjan(v)
 9              parent[v] = u
10      for each (u, v) in QUERY
11          if visit[v]
12              ans(u, v) = FIND(v)

我的理解:其实本质就是利用并查集。。在访问一个点的子树的时候,这个点其所有子树的祖先。。。由于祖先的节点比较小,所以merge的时候要f[大]=小…

要注意Tarjan 算法是离线算法。

哦对了。。这题要扩展语句才能过,不然会RE…

代码实现
  1#pragma comment(linker, "/STACK:1024000000,1024000000")
  2
  3
  4
  5
  6
  7
  8
  9
 10/* ***********************************************
 11Author :111qqz
 12Created Time :2016年04月12日 星期二 19时39分38秒
 13File Name :code/hdu/2586.cpp
 14************************************************ */
 15#pragma comment(linker, "/STACK:1024000000,1024000000")
 16#include <cstdio>
 17#include <cstring>
 18#include <iostream>
 19#include <algorithm>
 20#include <vector>
 21#include <queue>
 22#include <set>
 23#include <map>
 24#include <string>
 25#include <cmath>
 26#include <cstdlib>
 27#include <ctime>
 28#define fst first
 29#define sec second
 30#define lson l,m,rt<<1
 31#define rson m+1,r,rt<<1|1
 32#define ms(a,x) memset(a,x,sizeof(a))
 33typedef long long LL;
 34#define pi pair < int ,int >
 35#define MP make_pair
 36
 37using namespace std;
 38const double eps = 1E-8;
 39const int dx4[4]={1,0,0,-1};
 40const int dy4[4]={0,-1,1,0};
 41const int inf = 0x3f3f3f3f;
 42const int N = 4E4+7;
 43int n,q;
 44vector < pi > edge[N];
 45vector < pi >query[N];
 46bool vis[N];
 47int f[N];
 48int ans[N];
 49int dis[N];
 50void init()
 51{
 52    for ( int i = 1 ; i <= n ; i++) edge[i].clear();
 53    for ( int i = 1 ; i <= q ; i++) query[i].clear();
 54    ms(vis,false);
 55    for ( int i = 1 ; i <= n ; i++) f[i] = i ;
 56    ms(ans,0);
 57    ms(dis,0);
 58}
 59
 60int root ( int x)
 61{
 62    if (x!=f[x]) f[x]=root(f[x]);
 63    return f[x];
 64}
 65
 66void merge(int x,int y)
 67{
 68    int rx = root (x);
 69    int ry = root (y);
 70    if (rx!=ry)
 71    {
 72	f[ry] = rx;
 73    }
 74
 75}
 76
 77
 78void tarjan( int u,int val)
 79{
 80    vis[u] = true;
 81    dis[u] = val;
 82    int siz = edge[u].size();
 83    for ( int i = 0 ; i < siz ; i++)
 84    {
 85	int v = edge[u][i].fst;
 86	if (vis[v]) continue;
 87	tarjan(v,val+edge[u][i].sec);
 88	merge(u,v);
 89    }
 90    siz = query[u].size();
 91    for ( int i = 0 ; i < siz ; i++)
 92    {
 93	int v = query[u][i].fst;
 94	int id = query[u][i].sec;
 95	if (!vis[v]) continue;
 96	ans[id] = dis[u] + dis[v] -2*dis[root(v)];
 97    }
 98}
 99int main()
100{
101	#ifndef  ONLINE_JUDGE
102	freopen("code/in.txt","r",stdin);
103  #endif
104	ios::sync_with_stdio(false);
105	int T;
106	cin>>T;
107	while (T--)
108	{
109	    cin>>n>>q;
110	    init();
111	    for ( int i = 1 ; i <= n-1 ; i++)
112	    {
113		int u,v,w;
114		cin>>u>>v>>w;
115		edge[u].push_back(make_pair(v,w));
116		edge[v].push_back(make_pair(u,w));
117	    }
118
119	    for ( int i = 1 ; i <= q ; i++)
120	    {
121		int u,v;
122		cin>>u>>v;
123		query[u].push_back(make_pair(v,i));
124		query[v].push_back(make_pair(u,i));
125	    }
126
127	    tarjan(1,0);
128
129	    for ( int i = 1 ;i <= q ; i++) cout<<ans[i]<<endl;
130
131
132
133	}
134
135  #ifndef ONLINE_JUDGE
136  fclose(stdin);
137  #endif
138    return 0;
139}

相关文章

树边,前向边,后向边,横叉边

·727 字·2 分钟
转载自: 原文链接 树边,前向边,后向边,横叉边,应该说,不是一个图本身有的概念,应该是图进行DFS时才有的概念。图进行DFS会得到一棵DFS树(森林),在这个树上才有了这些概念。对图进行DFS,可以从任意的顶点开始,遍历的方式也是多样的,所以不同的遍历会得到不同的DFS树,进而产生不同的树边,前向边,后向边,横叉边。所以这4种边,是一个相对的概念。 在图的遍历中,往往设置了一个标记数组vis的bool值来记录顶点是否被访问过。但有些时候需要改变vis值的意义。令vis具有3种值并表示3种不同含义 vis = 0,表示该顶点没没有被访问 vis = 1,表示该顶点已经被访问,但其子孙后代还没被访问完,也就没从该点返回 vis = 2,,表示该顶点已经被访问,其子孙后代也已经访问完,也已经从该顶点返回 可以vis的3种值表示的是一种顺序关系和时间关系

BZOJ 1652: [Usaco2006 Feb]Treats for the Cows (区间dp)

·1352 字·3 分钟
1652: [Usaco2006 Feb]Treats for the Cows # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 290 Solved: 226 [Submit][Status][Discuss] Description # FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk. FJ sells one treat per day and wants to maximize the money he receives over a given period time. The treats are interesting for many reasons: * The treats are numbered 1..N and stored sequentially in single file in a long box that is open at both ends. On any day, FJ can retrieve one treat from either end of his stash of treats. * Like fine wines and delicious cheeses, the treats improve with age and command greater prices. * The treats are not uniform: some are better and have higher intrinsic value. Treat i has value v(i) (1 <= v(i) <= 1000). * Cows pay more for treats that have aged longer: a cow will pay v(i)*a for a treat of age a. Given the values v(i) of each of the treats lined up in order of the index i in their box, what is the greatest value FJ can receive for them if he orders their sale optimally? The first treat is sold on day 1 and has age a=1. Each subsequent day increases the age by 1.

BZOJ 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚 (前缀和)

·626 字·2 分钟
1651: [Usaco2006 Feb]Stall Reservations 专用牛棚 # Time Limit: 10 Sec Memory Limit: 64 MB Submit: 700 Solved: 393 [Submit][Status][Discuss] Description # Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reservation system to determine which stall each cow can be assigned for her milking time. Of course, no cow will share such a private moment with other cows. Help FJ by determining: * The minimum number of stalls required in the barn so that each cow can have her private milking period * An assignment of cows to these stalls over time

BZOJ 1650: [Usaco2006 Dec]River Hopscotch 跳石子 (二分)

·1042 字·3 分钟
1650: [Usaco2006 Dec]River Hopscotch 跳石子 # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 440 Solved: 290 [Submit][Status][Discuss] Description # Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 <= L <= 1,000,000,000). Along the river between the starting and ending rocks, N (0 <= N <= 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L). To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river. Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 <= M <= N). FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.