2013年scnu决赛B题_邻接矩阵保存图以及配对算法

题目如下:

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

You are given a tree with n vertices, each edge of it has a length(positive integer less than 10^9 ).
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 input contains several test cases.
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

For each test case output the answer on a single line.

Sample Input

5 3358
2 1 746
4 5 277
5 2 3057
3 5 1310

Sample Output

9

Author

lijunle

 

题目意思是给出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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值