POJ1987——Distance Statistics

Distance Statistics

Time Limit: 2000MS   Memory Limit: 64000K
Total Submissions: 1667   Accepted: 532
Case Time Limit: 1000MS

Description

Frustrated at the number of distance queries required to find a reasonable route for his cow marathon, FJ decides to ask queries from which he can learn more information. Specifically, he supplies an integer K (1 <= K <= 1,000,000,000)
and wants to know how many pairs of farms lie at a distance at most K from each other (distance is measured in terms of the length of road required to travel from one farm to another). Please only count pairs of distinct farms (i.e. do not count pairs such
as (farm #5, farm #5) in your answer).

Input

* Lines 1 ..M+1: Same input format as in "Navigation Nightmare"

* Line M+2: A single integer, K.

Output

* Line 1: The number of pairs of farms that are at a distance of at most K from each-other.

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
10

Sample Output

5

Hint

There are 5 roads with length smaller or equal than 10, namely 1-4 (3), 4-7 (2), 1-7 (5), 3-5 (7) and 3-6 (9).

Source

USACO 2004 February

求合法点对,树的点分治,和POJ1741差不多

#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 40010;
const int M = 40010;

struct node
{
	int weight;
	int next;
	int to;
}edge[M << 1];

int tot, res, ans, n, m, k, root, size;
int head[N], num[N], dp[N];
bool vis[N];
int dist[N];

void addedge(int from, int to, int weight)
{
	edge[tot].weight = weight;
	edge[tot].to = to;
	edge[tot].next = head[from];
	head[from] = tot++;
}

void get_root(int u, int fa)
{
	dp[u] = 0;
	num[u] = 1;
	for (int i = head[u]; ~i; i = edge[i].next)
	{
		int v = edge[i].to;
		if (v == fa || vis[v])
		{
			continue;
		}
		get_root(v, u);
		num[u] += num[v];
		dp[u] = max(dp[u], num[v]);
	}
	dp[u] = max(dp[u], size - num[u]);
	if (dp[root] > dp[u])
	{
		root = u;
	}
}

void calc_dist(int u, int d, int fa)
{
	dist[res++] = d;
	for (int i = head[u]; ~i; i = edge[i].next)
	{
		int v = edge[i].to;
		if (v == fa || vis[v])
		{
			continue;
		}
		calc_dist(v, d + edge[i].weight, u);
	}
}

int calc(int u, int d)
{
	res = 0;
	calc_dist(u, d, -1);
	int ret = 0;
	sort(dist, dist + res);
	int i = 0, j = res - 1;
	while (i < j)
	{
		while (i < j && dist[i] + dist[j] > k)
		{
			j--;
		}
		ret += j - i;
		i++;
	}
	return ret;
}

void solve()
{
	ans += calc(root, 0);
	vis[root] = 1;
	for (int i = head[root]; ~i; i = edge[i].next)
	{
		int v = edge[i].to;
		if (vis[v])
		{
			continue;
		}
		ans -= calc(v, edge[i].weight);
		root = 0;
		dp[0] = size = num[v];
		get_root(v, -1);
		solve();
	}
}

int main()
{
	int u, v, w;
	char dir[5];
	while (~scanf("%d%d", &n, &m))
	{
		memset( head, -1, sizeof(head) );
		memset ( num, 0, sizeof(num) );
		memset ( vis, 0, sizeof(vis) );
		tot = 0;
		ans = 0;
		root = 0;
		for (int i = 0; i < m; ++i)
		{
			scanf("%d%d%d%s", &u, &v, &w, dir);
			addedge(u, v, w);
			addedge(v, u, w);
		}
		scanf("%d", &k);
		dp[0] = size = n;
		get_root(1, -1);
		solve();
		printf("%d\n", ans);
	}
	return 0;
}
时间: 2024-10-16 02:09:37

POJ1987——Distance Statistics的相关文章

poj1987 Distance Statistics

普通dfs访问每个点对的复杂度是O(n^2)的,显然会超时. 考虑访问到当前子树的根节点时,统计所有经过根的点(u, v)满足: dist(u) + dist(v) <= maxd,并且 belong(u)≠belong(v)(即u,v不在同一子树). 这里说的距离指的是节点到跟的距离. 可以用作差法,即用所有满足条件的点对数减去那些在根节点为当前子树根节点的儿子节点的点对数. 上面一步可以用O(nlogn)的复杂度解决,即先排序再比较. 根节点子树可以递归解决,用树的点分治. 总复杂度上界是O

【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics

三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define MAXN 10001 typedef pair<int,int> Point; int n,K,ans; int v[MAXN<<1],w[MAXN<<1],first[MAXN],next[MAXN<<1],en; vo

POJ 1987 Distance Statistics 树分治

Distance Statistics Description Frustrated at the number of distance queries required to find a reasonable route for his cow marathon, FJ decides to ask queries from which he can learn more information. Specifically, he supplies an integer K (1 <= K

【poj1987】 Distance Statistics

http://poj.org/problem?id=1987 (题目链接) 题意 给出一棵树,求树上距离不超过K的点对个数. Solution 点分治,同poj1741. 代码 // poj1987 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL

【POJ1987】Distance Statistics ==【POJ1741】 树分治

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44307489"); } 题意&题解 http://blog.csdn.net/vmurder/article/details/44302921 代码:(同一道题) #include <cstdio> #inclu

POJ 1987 Distance Statistics (树上点分治)

题目地址:POJ 1987 点分治模板题,跟POJ 1741几乎一样,.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdi

bzoj 3365 [Usaco2004 Feb]Distance Statistics 路程统计(点分治,单调)

[题意] 求树上长度不超过k的点对数目. [思路] 和 Tree 一样一样的. 就是最后统计的时候别忘把根加上. [代码] 1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algori

POJ - 1987 Distance Statistics 树上的分治

题目大意:和poj 1741的那题和类似,求树上节点之间的距离小于等于k的节点对有多少对 解题思路:具体可参考:<分治算法在树的路径问题中的应用--漆子超> 给这题的输入坑了,注意输入,不然会超时 #include<cstdio> #include<vector> #include<algorithm> using namespace std; #define maxn 40010 int vis[maxn], Sum[maxn], d[maxn], dp[

POJ 1987 BZOJ 3365 Distance Statistics 树的分治(点分治)

题目大意:(同poj1741,刷一赠一系列) CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 40010 #define INF 0x3f3f3f3f using namespace std; int points,edges,k; int head[MAX],total; int next[MAX <<