10 10 10 7 2 1 6 8 3 4 5 8 5 8 2 2 8 9 6 4 5 2 1 5 8 10 5 7 3 7 7 8 8 10 6 1 5 9 1 8 2 7 6
36 13 1 13 36 1 36 2 16 13
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//按照边大小排序,依次合并两端点,则以此边为路上最大长度
//的路径共有 num[x]*num[y];
//将要查询的L从小到大排序,依次处理即可
const int maxn=51000;
int fath[maxn];
int num[maxn];
int n;
void init()
{
for(int i=1;i<=n;i++) fath[i]=i,num[i]=1;
}
int find(int x)
{
return fath[x]==x?x:fath[x]=find(fath[x]);
}
int uion(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return 0;
int cnt=num[x]*num[y];
if(num[x]<num[y])
{
fath[x]=y;
num[y]+=num[x];
}
else
{
fath[y]=x;
num[x]+=num[y];
}
return cnt;
}
struct Edge
{
int u,v,w;
};
Edge edge[maxn];
bool cmpEdge(Edge h,Edge k)
{
return h.w<k.w;
}
struct Node
{
int val;
int index;
};
Node ind[maxn];
bool cmpNode(Node h,Node k)
{
return h.val<k.val;
}
int ans[maxn];
int main()
{
int m,q;
while(scanf("%d%d%d",&n,&m,&q)==3)
{
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge,edge+m,cmpEdge);
for(int i=0;i<q;i++)
{
scanf("%d",&ind[i].val);
ind[i].index=i;
}
sort(ind,ind+q,cmpNode);
init();
int sum=0;
int l=0;
for(int i=0;i<m;i++)
{
int u=edge[i].u,v=edge[i].v,w=edge[i].w;
int tmp=uion(u,v);
sum+=tmp;
while(l<q&&w>ind[l].val) ans[ind[l++].index]=sum-tmp;
}
for(int i=l;i<q;i++) ans[ind[i].index]=ans[ind[i-1].index];
for(int i=0;i<q;i++) printf("%d\n",ans[i]);
}
return 0;
}

本文介绍了一种用于计算图中特定能量限制下最长边路径数量的算法。该算法通过按边权重排序并使用并查集来高效地解决这一问题。输入包含节点数、边数及查询次数等信息,输出则为不同能量水平下可形成的路径数量。
11万+

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



