zoukankan      html  css  js  c++  java
  • 2013南京网赛1003 hdu 4750 Count The Pairs

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4750

    题意:给出一个无向图,f(a,b)表示从点a到点b的所有路径中的每条路径的最长边中的最小值,给出 p个询问,每个询问有一个数t,对于每个询问,求有多少对顶点f(a,b)小于t。注意(1,2)和(2,1)是不同的点对

    分析:

    正过来想不太好做..反过来..看在当前t的限制下..有多少个点对f(u,v)<t...这样答案就是totol-sum...totol是总对数n*(n-1)...sum是当前可联通的..

    这样转化后就不难想到将所有的询问从小到大排序..将所有的边从小到大排序..然后根据递增的询问不断地加边统计答案..而要统计答案和维护图的联通关系时用到并查集....如此时间复杂度为O(m).有点像模拟最小生成树的Kurskal

    对于每一条边(a,b),判断两个端点a,b是否属于同一个集合,如果不是,则当前边就是a,b所有路径中要求的“瓶颈边”(因为所有的边是从小到大排序的),这时小于t的点对数为sum加上这两个集合的顶点点个数乘积的两倍,即sum+=num[f1]*num[f2]*2,最后对于每个询问输出total-sum即可。

    AC代码如下:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 struct NODE
     6 {
     7     int u,v,w;
     8     bool operator <(const NODE &a)const{
     9         return w<a.w;
    10     }
    11 }node[500005];
    12 struct T
    13 {
    14     int d,id;
    15     bool operator <(const T &a)const{
    16         return d<a.d;
    17     }
    18 }t[100005];
    19 int num[10005],fa[10005],ans[100005];
    20 int find(int x)
    21 {
    22     if(x!=fa[x])
    23         fa[x]=find(fa[x]);
    24     return fa[x];
    25 }
    26 int main()
    27 {
    28     int n,m,j,i,p;
    29     while(scanf("%d%d",&n,&m)!=EOF)
    30     {
    31         for(i=0;i<m;i++)
    32             scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);
    33         scanf("%d",&p);
    34         for(i=0;i<p;i++)
    35         {
    36             scanf("%d",&t[i].d);
    37             t[i].id=i;
    38         }
    39         sort(node,node+m);
    40         sort(t,t+p);
    41         for(i=0;i<n;i++)
    42         {
    43             fa[i]=i;
    44             num[i]=1;
    45         }
    46         int total=n*(n-1);
    47         int sum=0;
    48         j=0;
    49         for(i=0;i<p;i++)
    50         {
    51             while(j<m&&node[j].w<t[i].d)
    52             {
    53                 int f1=find(node[j].u);
    54                 int f2=find(node[j].v);
    55                 if(f1==f2)
    56                 {
    57                     j++;
    58                     continue;
    59                 }
    60                 sum+=num[f1]*num[f2]*2;
    61                 fa[f1]=f2;
    62                 num[f2]+=num[f1];
    63                 j++;
    64             }
    65             ans[t[i].id]=total-sum;
    66         }
    67         for(i=0;i<p;i++)
    68             printf("%d
    ",ans[i]);
    69     }
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    Redis 哨兵机制以及灾难演练
    经典的Redis的主从复制搭建
    Redis的几个核心机制底层原理
    Redis Sentinel(哨兵核心机制) 初步深入
    从零开始装CentOS以及配置Redis,前端都可以!!!
    在项目中部署redis的读写分离架构(包含节点间认证口令)
    读懂MySQL执行计划
    SpringBoot之自动配置原理
    排序算法总结
    拉格朗日插值法理论与编程实现
  • 原文地址:https://www.cnblogs.com/frog112111/p/3335554.html
Copyright © 2011-2022 走看看