hdu5441

Travel

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1225    Accepted Submission(s): 443

Problem Description

Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m
bidirectional roads connecting the cities. Jack hates waiting too long
on the bus, but he can rest at every city. Jack can only stand staying
on the bus for a limited time and will go berserk after that. Assuming
you know the time it takes to go from one city to another and that the
time Jack can stand staying on a bus is x minutes, how many pairs of city (a,b) are there that Jack can travel from city a to b without going berserk?

Input

The first line contains one integer T,T≤5, which represents the number of test case.

For each test case, the first line consists of three integers n,m and q where n≤20000,m≤100000,q≤5000. The Undirected Kingdom has n cities and m bidirectional roads, and there are q queries.

Each of the following m lines consists of three integers a,b and d where a,b∈{1,...,n} and d≤100000. It takes Jack d minutes to travel from city a to city b and vice versa.

Then q lines follow. Each of them is a query consisting of an integer x where x is the time limit before Jack goes berserk.

Output

You should print q lines for each test case. Each of them contains one integer as the number of pair of cities (a,b) which Jack may travel from a to b within the time limit x.

Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.

Sample Input

1
5 5 3
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000

Sample Output

2
6
12

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=20010;
const int maxm=100010;
const int maxq=5005;
struct node1{
   int u,v,w;
   node1(){}
   node1(int u,int v,int w):u(u),v(v),w(w) {}
}g[maxm];

struct node2{
   int d,id;
   node2(){}
   node2(int d,int id):d(d),id(id) {}
}que[5005];
long long  ans[5005];
int num[maxn], rak[maxn],father[maxn];
bool cmp1(struct node1 t1,struct node1 t2){
      return t1.w<t2.w;
}
bool cmp2(struct node2 t1,struct node2 t2){
   return t1.d<t2.d;
}

int find(int x){
   if(x!=father[x])
       father[x]=find(father[x]);
    return father[x];
}
long long  tnum;
void Union(int u,int v){
    int x=find(u);
    int y=find(v);
    if(x==y)
        return ;
    tnum+=num[x]*num[y];

    if(rak[x]<rak[y]){
           father[x]=y;
           num[y]+=num[x];
           num[x]=0;
    }
    else {
        father[y]=x;
       if(rak[x]==rak[y])
            ++rak[x];
       num[x]+=num[y];
       num[y]=0;
    }
}

int main(){
   int t;
   scanf("%d",&t);
   while(t--){
      int n,m,q;

      scanf("%d%d%d",&n,&m,&q);
      int u,v,w;

    for(int i=1;i<=n;i++){
      father[i]=i;
      num[i]=1;
      rak[i]=0;
    }

      for(int i=0;i<m;i++){
          scanf("%d%d%d",&u,&v,&w);
           g[i]=node1(u,v,w);
      }
      sort(g,g+m,cmp1);
      int d;
      for(int i=0;i<q;i++){
        scanf("%d",&d);
        que[i]=node2(d,i);
      }
      sort(que,que+q,cmp2);
        memset(ans,0,sizeof(ans));
      tnum=0;
      for(int i=0,j=0;i<q;i++){
          int cur=que[i].d;
          while(j<m){
            node1 temp=g[j];

             if(cur>=temp.w){

                Union(temp.u,temp.v);
             }
             else
                 break;
             j++;
          }
         ans[que[i].id]=tnum;
      }
      for(int i=0;i<q;i++)
          printf("%lld\n",ans[i]*2);

   }
   return 0;
}
时间: 2024-10-13 02:42:30

hdu5441的相关文章

hdu5441 并查集+克鲁斯卡尔算法

这题计算 一张图上 能走的 点对有多少个  对于每个限制边权 , 对每条边排序,对每个查询排序 然后边做克鲁斯卡尔算法 的时候变计算就好了 #include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <vector> #include <queue> using namespace std; const int maxn

hdu5441(2015长春赛区网络赛1005)类最小生成树、并查集

题意:有一张无向图,一些点之间有有权边,某条路径的值等于路径上所有边的边权的最大值,而某个点对的值为这两点间所有路径的值的最小值,给出多个询问,每个询问有一个值,询问有多少点对满足其值小于等于询问值.点的顺序不同算作不同点对. 这题的做法很类似Kruskal算法.一开始所有的点都为一个并查集,从权值最小的边开始,当加入这条边的时候,这条边连接的两个点(并查集)之间相互到达的路径中,值最小的一个路径一定就是通过这条边的,所以这两点间的值就是这条边的权值.之后每加入一条最小边,如果可以用来合并两个并

HDU5441 Travel (离线操作+并查集)

Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2055    Accepted Submission(s): 709 Problem Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is tr

hdu5441 并查集 长春网赛

对于每次询问的大的值,都是从小的值开始的,那就从小到大处理,省去很多时间,并且秩序遍历一遍m; 这题cin容易超时,scanf明显快很多很多.G++又比C++快; //这代码scanf400+,cin800+ 并且我交了快10次cin的8次超时 //scanf代码C++400+,G++250+ #include<cstring> #include<iostream> #include<algorithm> #define maxn 20010 using namespa

hdu5441(并查集+离线处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意: 根据输入的三个整数n.m.q,表示有n座城市,m条路,q次询问.下面给出m行,每行三个数start.end.w,分别是这条道路的起点城市.终点城市."权值".然后给出q次询问的数值,每次询问的结果是符合条件的路有多少条.条件就是:如果这条路的权值比给的限制值要小,那么这条路就是可行的.注意就是:对于一条路的添加来说,只要a到b之间有路,那么符合条件的路就会有两条,一条是a到b

HDU-5441 Travel 离线-并查集

Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 4680    Accepted Submission(s): 1532 Problem Description Jack likes to travel around the world, but he doesn't like to wait. Now, he is t