hdu 4750 Count The Pairs

来源:互联网 发布:手机淘宝论坛怎么找 编辑:程序博客网 时间:2024/06/05 17:56

        题意:一个无向图,n个点m条边,定义每条路径的价值是路径上最长边的长路,每个点对的价值是点对中所有路径的最小价值。有p次询问,每次询问一个值t,问有多少组点对的价值超过p。

        思路:本来先是用的Floyd,爆内存,然后用n次SPFA,超时。应该在做题前分析复杂度的。。。正确的做法是联想kruskal算法和并查集,在合并的时候,增加的_价值为当前合并边长度的_点对数量为_待合并两个集合的_大小的_积。。。前面的下划线是为了断句。。处理询问的时候,因为价值的范围太大了,需要离散化处理,然后二分搜答案。


#include <iostream>      #include <stdio.h>      #include <cmath>      #include <algorithm>      #include <iomanip>      #include <cstdlib>      #include <string>      #include <memory.h>      #include <vector>      #include <queue>      #include <stack>      #include <map>    #include <set>    #include <ctype.h>      #define INF 1000000010  #define ll long long  #define max3(a,b,c) max(a,max(b,c))  #define MAXN 100010  using namespace std;struct edge{    int u;int v;    int w;};edge E[500010];bool cmp(edge e1,edge e2){return e1.w<e2.w;}int p[10010];int find(int x){if(x!=p[x])p[x]=find(p[x]);return p[x];}int setsize[10010];void _union(int a,int b){int fa=find(a);int fb=find(b);p[fa]=fb;setsize[fb]+=setsize[fa];}map<ll,int> mp;int cnt[500010];int num[500010];int ans[10010];int main(){    int n,m;    while(cin>>n>>m){        for(int i=0;i<n;i++)p[i]=i;        for(int i=0;i<n;i++)setsize[i]=1;                memset(cnt,0,sizeof(cnt));        memset(num,0,sizeof(num));        mp.clear();                for(int i=1;i<=m;i++){            int a,b,c;            scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);        }                sort(E+1,E+m+1,cmp);                for(int i=1;i<=m;i++){int u=E[i].u;int v=E[i].v;int fu=find(u);int fv=find(v);int su=setsize[fu];int sv=setsize[fv];if(fu!=fv){mp[E[i].w]+=su*sv*2; _union(u,v);}}               int q=1;        for(map<ll,int>::iterator it=mp.begin();it!=mp.end();it++){            num[q]=it->first;            cnt[q]=it->second;            q++;        }                int size=mp.size();        num[size+1]=INF;        for(int i=size;i>=0;i--){            cnt[i]+=cnt[i+1];          }                int p;        cin>>p;        for(int k=0;k<p;k++){            int t;            scanf("%d",&t);                        int l=0;            int r=size+1;            while(true){                                int mid=(r+l)/2;                                if(num[mid]==t){                    printf("%d\n",cnt[mid]);                    break;                }                                if(num[mid]>t){                    r=mid;                }else{                    if(num[mid+1]>t){                                                printf("%d\n",cnt[mid+1]);                        break;                    }                    l=mid;                }            }          }    }    return 0;}


0 0