题目链接
题意:先建立M条边,然后查询在L能量下能走多少条边的走法,然后看到查询的个数与查询的权值,我们可以通过按权值升序来做一个优化。
思路:我们要想知道所有符合条件的走法,可以先研究一下题目中给的样例中L==5时候的可能,会有这样的走法:
{1->2}、{2->7}、{1->7}、
{6->8}、{5->8}、{8->10}、{4->6}、{4->8}、{6->10}、{5->10}、{4->5}、{5->6}、{4->10}
这么几种走法,然后我们来推一下种类数与ans的关系,看到1、2、7这几个点的答案,种类可能是3,先把1连接到2上,可以看作2上的子节点多了一,然后这是方案一,然后把2连接到7上,7的子节点就有2个了,但是看前缀,相当于把2节点上的两个节点按两种方式连接到单一的7上,所以应当加的方案数是2*1==2。
按照上面的做法,我们推其他的可能,会发现所有的节点都符合这样的条件,加上去的边权为sum[根1]*sum[根2]。
剩下的就是对于查询的L的按升序的处理了,自己思考吧,挺简单的,一半是惯用的思维。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=1e4+5;
int N, M, Q, root[maxN];
ll sum[maxN];
struct Eddge
{
int no, to, val;
Eddge(int a=0, int b=0, int c=0):no(a), to(b), val(c) {}
}edge[5*maxN];
bool cmp_ed(Eddge e1, Eddge e2) { return e1.val<e2.val; }
struct Query
{
int ques, id;
ll sum;
Query(int a=0, int b=0, ll c=0):ques(a), id(b), sum(c) {}
}qq[maxN];
bool cmp_qu(Query e1, Query e2) { return e1.ques<e2.ques; }
bool cmp_qu2(Query e1, Query e2) { return e1.id<e2.id; }
void init()
{
for(int i=1; i<=N; i++) { root[i]=i; sum[i]=1; }
}
int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); }
ll mix(int x, int y)
{
int u=fid(x), v=fid(y);
if(u == v) return 0;
ll ans=sum[u]*sum[v];
if(sum[u]>sum[v]) swap(u, v); //可有可无,爱好问题
root[u]=v;
sum[v]+=sum[u];
return ans;
}
int main()
{
while(scanf("%d%d%d", &N, &M, &Q)!=EOF)
{
for(int i=1; i<=M; i++)
{
scanf("%d%d%d", &edge[i].no, &edge[i].to, &edge[i].val);
}
sort(edge+1, edge+1+M, cmp_ed);
for(int i=1; i<=Q; i++)
{
scanf("%d", &qq[i].ques);
qq[i].id=i;
}
sort(qq+1, qq+1+Q, cmp_qu);
init();
int j=1;
ll sum=0;
for(int i=1; i<=M && j<=Q; )
{
if(qq[j].ques >= edge[i].val)
{
sum+=mix(edge[i].no, edge[i].to);
i++;
}
else
{
qq[j++].sum=sum;
}
}
while(j<=Q) { qq[j].sum=sum; j++; }
sort(qq+1, qq+1+Q, cmp_qu2);
for(int i=1; i<=Q; i++) printf("%lld\n", qq[i].sum);
}
return 0;
}