题目如下:
A simple tree problem
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 238 Accepted Submission(s) : 45
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
The n vertices is numbered from 1 to n. We will assume that root of tree always is 1.
We define dist(u) as the min distance between node u and root.
Given an integer k, a pair (u, v) of vertices is called valid if and only if dist(u) + dist(v) ≥ k
(1 <= u, v <= n, u != v, k <= 10^9 ).
Write a program to count how many pairs are valid for a given tree. Noting that we think pair
(u, v) is the same as pair (v, u) , so just count once.
Input
The first line of each test case contains two integers n, k (2 <= n <= 30, 000).
The following n-1 lines each contains three integers u, v, l, which means there is an edge between
node u and v of length l.
Output
Sample Input
5 3358 2 1 746 4 5 277 5 2 3057 3 5 1310
Sample Output
9
Author
题目意思是给出n, k的值,然后输入n-1条边(边序号保证在n以内)。输入n, k以后的n-1行内分别输入结点编号以及他们之间的距离。输入完毕后,找出有多少对结点满足他们到原点(原点固定为“1”)的距离和大于或等于k值。
用邻接矩阵做,代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <CSTDIO>
using namespace std;
const int maxn = 30000 + 100;
struct Node
{
int num; //num保存编号,distant两点间的距离。
__int64 distant; //这里小心输入,题目的数据比较大
};
vector<Node> G[maxn]; //保存邻接矩阵的Node类型的vector数组
/*int p[maxn];*/
__int64 dis[maxn];
void dfs(Node u, Node fa)
{
int d = G[u.num].size();
int i;
for (i = 0; i < d; i++)
{
Node v = G[u.num][i];
if(v.num != fa.num)
{
dis[v.num] = dis[u.num] + v.distant; //一直计算出每一个结点到原点的距离。保存在dis数组中后面使用。
dfs(v, u);
}
}
}
int main()
{
int n, k;
while(scanf("%d%d",&n,&k)==2)
{
int cl;
for (cl = 0; cl < n + 2; cl++)G[cl].clear();
dis[1] = 0;
int c;
for(c = 1; c < n; c++)
{
Node a, b;
scanf("%d%d%I64d",&a.num,&b.num,&b.distant);
a.distant = b.distant;
G[a.num].push_back(b); //保存邻接矩阵
G[b.num].push_back(a);
}
Node root;
root.num = 1;
root.distant = 0;
Node father;
father.num = -1;
dfs(root, father);
sort(dis+1,dis+1+n); //先排序
int i;
int count = 0; //保存对数
int j = 2;
for (i = 1; i < n; ) //扫完后退出
{
if(dis[i] + dis[n] >= k)
{
count = count + n - i ; //从前面扫到第一个与n相加大于或等于k的数,那么对数就增加 n - i 个
n--; //找到之后n减一,从 i 的位置继续扫。
continue;
}
i++; // i++ 继续扫到满足条件为止
}
printf("%d\n",count);
}
return 0;
}