Travel
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.
Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
1 5 5 3 2 3 6334 1 5 15724 3 5 5705 4 3 12382 1 3 21726 6000 10000 13000
2 6 12
【思路分析】
参照别人的思路写的。。。这类题一定要多加训练。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2e4 + 50;
const int maxm = 1e5 + 50;
const int maxq = 5e3 + 50;
int n,m,q,sum;
int sets[maxn],ans[maxn],number[maxn];
struct Edge
{
int u,v,w;
Edge()
{
}
Edge(int u,int v,int w) : u(u),v(v),w(w)
{
}
bool operator < (const Edge &e) const
{
return w < e.w;
}
}edge[maxm];
struct Query
{
int val,index;
bool operator < (const Query &q) const
{
return val < q.val;
}
}query[maxq];
void init()
{
sum = 0;
scanf("%d %d %d",&n,&m,&q);
for(int i = 1;i <= n;i++)
{
sets[i] = i;
number[i] = 1;
}
for(int i = 1;i <= m;i++)
{
scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
}
for(int i = 1;i <= q;i++)
{
scanf("%d",&query[i].val);
query[i].index = i;
}
sort(edge + 1,edge + m + 1);
sort(query + 1,query + q + 1);
}
int finding(int x)
{
return sets[x] = (sets[x] == x ? x : finding(sets[x]));
}
void merging(int a,int b)
{
int p1 = finding(a);
int p2 = finding(b);
if(p1 != p2)
{
int x = number[p1];
int y = number[p2];
sum -= x * (x - 1);//即x个结点两两之间边的权值满足条件的点对数
sum -= y * (y - 1);
sets[p1] = p2;
number[p2] += number[p1];
number[p1] = 0;//以上三步将集合a并入集合b
sum += (number[p2]) * (number[p2] - 1);
}
}
void solve()
{
int num = 1;
for(int i = 1;i <= q;i++)
{
while(num <= m && edge[num].w <= query[i].val)//权值不大于q值时进行合并
{
merging(edge[num].u,edge[num].v);
num++;
}
ans[query[i].index] = sum;
}
for(int i = 1;i <= q;i++)
printf("%d\n",ans[i]);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
solve();
}
return 0;
}
7478



被折叠的 条评论
为什么被折叠?



