HDU 5441 Travel(最短路径变形)

/*题意:有一个n个点的无向图,给出m条边的边权,给出q次询问,每次给出一个值,求用到所有边权不大于这个值的边的情况下,能够互相到达的点对的个数(自己到自己不算)
分析:
先把路线按照权值从小到大排序,然后再把那几个值按从小到大排序。后面就是一系列最短路径问题了,貌似不难*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxm=1e5;
int n,m,k;
int num[maxm];
int p[maxm];
int ans[maxm];
void Init()
{
    for(int i=0;i<=maxm;i++)
    {
        p[i]=i;
        num[i]=1;
    }
}
struct node
{
    int u,v,c;
    bool operator<(const node &s)const
    {
        return c<s.c;
    }
}t[maxm];
struct NODE
{
    int w,id;
    bool operator<(const NODE &p)const
    {
        return w<p.w;
    }

}T[maxm];
int find(int k)
{
    if(p[k]!=k)
    {
        return p[k]=find(p[k]);
    }
    else
    {
        return p[k];
    }
}
int main()
{
    int y;
    scanf("%d",&y);
    while(y--)
    {
        Init();
        memset(ans,0,sizeof(ans));
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].c);
        }
        sort(t,t+m);
        for(int i=0;i<k;i++)
        {
            scanf("%d",&T[i].w);
            T[i].id=i;
        }
        sort(T,T+k);
        int j=0;
        int cnt=0;
        for(int i=0;i<k;i++)
        {
            while(j<m&&t[j].c<=T[i].w)
            {
                int x=find(t[j].u);
                int y=find(t[j].v);
                j++;
                if(x!=y)
                {
                    p[x]=y;
                    cnt+=(num[x]*num[y]);
                    num[y]+=num[x];
                }
            }
            ans[T[i].id]=2*cnt;
        }
        for(int i=0;i<k;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}

你可能感兴趣的:(HDU 5441 Travel(最短路径变形))