题意:
定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t的点对有所少对..注意(1,2)和(2,1)是不同的点对...
题解:
正过来想不太好做..反过来..看在当前t的限制下..有多少个点对f(u,v)<t...这样答案就是totol-num...totol是总对数n*(n-1)...num是当前可联通的..
这样转化后就不难想到将所有的询问从小到大排序..将所有的边从小到大排序..然后根据递增的询问不断地加边统计答案..而要统计答案和维护图的联通关系时用到并查集....如此时间复杂度为O(m)..
Program:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdlib>
#include<stack>
#include<map>
#define MAXN 10005
#define MAXM 1000505
#define ll long long
#define eps 1e-10
using namespace std;
struct node
{
int x,y,d,next;
}edge[MAXM];
struct NODE1
{
int x,y,d;
}E[MAXM];
struct NODE2
{
ll w,id;
}q[MAXM];
int father[MAXN];
ll ans[MAXM],num[MAXN];
bool cmp1(NODE1 a,NODE1 b)
{
return a.d<b.d;
}
bool cmp2(NODE2 a,NODE2 b)
{
return a.w<b.w;
}
int getfather(int x)
{
if (father[x]==x) return x;
return father[x]=getfather(father[x]);
}
int main()
{
int n,m,x,y,d,p,i,t;
ll totol,A;
while(~scanf("%d%d",&n,&m))
{
for (i=1;i<=m;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].d);
scanf("%d",&p),totol=n*(n-1);
for (i=1;i<=p;i++) scanf("%I64d",&q[i].w),q[i].id=i;
sort(E+1,E+1+m,cmp1),sort(q+1,q+1+p,cmp2);
for (i=0;i<n;i++) father[i]=i,num[i]=1;
A=0,t=1;
for (i=1;i<=p;i++)
{
d=q[i].w;
while (t<=m && E[t].d<d)
{
x=getfather(E[t].x),y=getfather(E[t].y);
if (x==y) { t++; continue; }
A+=num[x]*num[y]*2;
num[y]+=num[x];
father[x]=y;
t++;
}
ans[q[i].id]=totol-A;
}
for (i=1;i<=p;i++) printf("%I64d\n",ans[i]);
}
return 0;
}