• HDU 5441 Travel


    题意:一个不愿意做在bus等时间的人想去旅游,给出n个城市,m条道路和q个询问

    题意思路参考:传送门

    PS:暴力求n次最小生成树肯定超时、因为边的个数达到了10的5次方

     1 #include<cmath>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 int n,m,q;
     7 const int qq=20005;
     8 int pre[qq];
     9 int sum[qq];
    10 int tar[qq];
    11 struct Edge
    12 {
    13     int u,v,w;
    14     bool operator < (Edge a)const
    15     {
    16         return w<a.w;
    17     }
    18 }edge[qq*5];
    19 struct Query
    20 {
    21     int money;
    22     int order;
    23     bool operator < (Query b)const
    24     {
    25         return money<b.money;        //总是忘记带return
    26     }
    27 }query[qq];
    28 int find(int x)
    29 {
    30     if(x==pre[x])    return x;
    31     return pre[x]=find(pre[x]);
    32 }
    33 void slove()
    34 {
    35     for(int i=1;i<=n;++i){
    36         pre[i]=i;            
    37         sum[i]=1;        //初始化每一个连通块 
    38     }
    39     int ans=0;
    40     int j=0;
    41     for(int i=0;i<q;++i){
    42         for(;j<m && edge[j].w<=query[i].money;++j){
    43             int u,v;
    44             u=edge[j].u;v=edge[j].v;
    45             int x=find(u);int y=find(v);
    46             if(x==y) continue;
    47             ans+=sum[x]*sum[y]; //当连通块x和连通块y要形成一个新的连通块时,会增加多少两两组合的城市? 
    48             pre[y]=x;    //这里的城市对是一个组合、不是有序对 
    49                     //也就是说连通块x的每一个元素都可以和连通块y中的任意一个元素组成新的城市对
    50                         //所以这里是连通块x的元素个数去乘连通块y的元素个数、
    51             sum[x]=sum[x]+sum[y];     //两个连通块连接成一个连通块、更新连通块的元素个数 
    52         }                             
    53         tar[query[i].order]=ans*2;    //因为是有序对、所以要乘2 、 
    54     }                                //对应顺序来填值、 
    55     for(int i=0;i<q;++i)
    56         printf("%d
    ",tar[i]);
    57 }
    58 int main()
    59 {
    60     int t;scanf("%d",&t);
    61     while(t--){
    62         scanf("%d%d%d",&n,&m,&q);
    63         for(int i=0;i<m;++i)
    64             scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    65         for(int i=0;i<q;++i){
    66             scanf("%d",&query[i].money);
    67             query[i].order=i;            //记录标号、以便用数组来填值 
    68         }
    69         sort(edge,edge+m);
    70         sort(query,query+q);
    71         slove();
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    系统设计题:如何设计一个电商平台积分兑换系统!
    服务器上部署多台mysql
    log4j日志输出格式一览
    Intellij IDEA 智能补全
    什么是旅行商问题——算法NP、P、NPC知识
    如何找到两个升序数组归并后的升序数组的中位数
    Java 不同进制的字面值
    Android 进程和线程
    美图秀秀2015年实习生android应用开发方向招聘笔试题
    Android:Layout_weight的深刻理解
  • 原文地址:https://www.cnblogs.com/sasuke-/p/5453340.html
Copyright © 2020-2023  润新知