zoukankan      html  css  js  c++  java
  • hdu4750Count The Pairs(最小生成树找瓶颈边)

     1 /*
     2    题意:就是给你一个图,图的每两个点都有多条路径,每一条路径中都有一条最大边,
     3    所有最大边的最小边(也就是瓶颈边)就是这两点之间的val值!然后给你一个值f,
     4    问有多少个顶点对的val>=f! (u,v) 和 (v, u)是不同的顶点对!
     5 
     6    思路:最小生成树(kruskral)那么每两个节点(u,v)的瓶颈边就是这一棵树中u到v
     7          的路径中的最大边值!
     8          在利用并查集的过程中,A, B两个集合,如果有u属于A,v属于B,且u-v可以将
     9          A-B集合连接起来,因为边值由小到大选取,那么以u-v边为瓶颈边的节点的个数
    10          就是[A]*[B]*2;
    11 
    12    注意:图不一定是连通的,开始的时候当成了一棵树,怎么改都不对!
    13 */
    14 #include<iostream>
    15 #include<cstring>
    16 #include<cstdio>
    17 #include<algorithm>
    18 #define N 10105
    19 #define M 500105
    20 using namespace std;
    21 int f[N];
    22 struct Edge{
    23     int u, v, w;
    24     Edge(){}
    25     Edge(int u, int v, int w){
    26         this->u=u;
    27         this->v=v;
    28         this->w=w;
    29     }
    30 };
    31 
    32 Edge edge[M];
    33 int dist[N];
    34 int rank[N];
    35 int cnt[N];
    36 int edgeN;
    37 int sumN[N];
    38 int n, m;
    39 
    40 bool cmp(Edge a, Edge b){
    41    return a.w < b.w;
    42 }
    43 
    44 int getFather(int x){
    45    return x==f[x] ? x : f[x]=getFather(f[x]);
    46 }
    47 
    48 bool Union(int a, int b){
    49    a=getFather(a); 
    50    b=getFather(b);
    51    if(a!=b){
    52       cnt[++edgeN]=sumN[a]*sumN[b]*2;//记录以这一条边为瓶颈边的节点对的个数
    53       if(rank[a]>rank[b]){
    54           f[b]=a;
    55           sumN[a]+=sumN[b];//将b集合放入到a集合中去
    56       }
    57       else{
    58          f[a]=b;
    59          sumN[b]+=sumN[a];//将a集合放入到b集合中去
    60          ++rank[b];
    61       }
    62       return true;
    63    }
    64    return false;
    65 }
    66 
    67 void Kruskral(){
    68    edgeN=0;
    69    sort(edge, edge+m, cmp);
    70    for(int i=1; i<=n; ++i)
    71       f[i]=i, rank[i]=0, sumN[i]=1;
    72    for(int i=0; i<m; ++i)
    73     if(Union(edge[i].u, edge[i].v))
    74        dist[edgeN]=edge[i].w;//记录最小生成树中的边值
    75    cnt[edgeN+1]=0;
    76    for(int i=edgeN; i>=1; --i)//统计大于等于第i条边为瓶颈边边值的所有节点对的对数
    77        cnt[i]+=cnt[i+1];
    78 }
    79 
    80 int main(){
    81     int p;
    82     while(scanf("%d%d", &n, &m)!=EOF){
    83         for(int i=0; i<m; ++i){
    84            int u, v, w;
    85            scanf("%d%d%d", &u, &v, &w);
    86            edge[i]=Edge(u+1, v+1, w);
    87         }
    88         Kruskral();
    89         scanf("%d", &p);
    90         while(p--){
    91            int x;
    92            scanf("%d", &x);
    93            int index=lower_bound(dist+1, dist+edgeN+1, x)-dist;
    94            if(index>edgeN) printf("0
    ");
    95            else printf("%d
    ", cnt[index]);
    96         }
    97     }
    98     return 0;
    99 }

    //如果最后只有一棵树的话,这样做就可以了!没想到可能不是仅仅一棵树
    1
    #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define N 10105 6 #define M 500105 7 using namespace std; 8 int f[N]; 9 struct Edge{ 10 int u, v, w; 11 Edge(){} 12 Edge(int u, int v, int w){ 13 this->u=u; 14 this->v=v; 15 this->w=w; 16 } 17 }; 18 19 Edge edge[M]; 20 int dist[N]; 21 int rank[N]; 22 int cnt[N]; 23 int edgeN; 24 25 int n, m; 26 27 bool cmp(Edge a, Edge b){ 28 return a.w < b.w; 29 } 30 31 int getFather(int x){ 32 return x==f[x] ? x : f[x]=getFather(f[x]); 33 } 34 35 bool Union(int a, int b){ 36 a=getFather(a); 37 b=getFather(b); 38 if(a!=b){ 39 if(rank[a]>rank[b]) 40 f[b]=a; 41 else{ 42 f[a]=b; 43 ++rank[b]; 44 } 45 return true; 46 } 47 return false; 48 } 49 50 void Kruskral(){ 51 edgeN=0; 52 sort(edge, edge+m, cmp); 53 for(int i=1; i<=n; ++i) 54 f[i]=i, rank[i]=0; 55 for(int i=0; i<m; ++i) 56 if(Union(edge[i].u, edge[i].v)) 57 dist[++edgeN]=edge[i].w; 58 cnt[edgeN+1]=0; 59 for(int i=edgeN; i>=1; --i){ 60 cnt[i]=i*2; 61 cnt[i]+=cnt[i+1]; 62 } 63 } 64 65 int main(){ 66 int p; 67 while(scanf("%d%d", &n, &m)!=EOF){ 68 for(int i=0; i<m; ++i){ 69 int u, v, w; 70 scanf("%d%d%d", &u, &v, &w); 71 edge[i]=Edge(u+1, v+1, w); 72 } 73 Kruskral(); 74 scanf("%d", &p); 75 while(p--){ 76 int x; 77 scanf("%d", &x); 78 int index=lower_bound(dist+1, dist+edgeN+1, x)-dist; 79 if(index>edgeN) printf("0 "); 80 else printf("%d ", cnt[index]); 81 } 82 } 83 return 0; 84 }
  • 相关阅读:
    计算机的组成与操作系统
    面向对象初识
    规范化目录
    装饰器进阶
    装饰器练习
    装饰器
    内置函数二 闭包
    生成器 推导式 练习
    迭代器 递归 格式化 练习
    生成器 推导式 内置函数
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/3943331.html
Copyright © 2011-2022 走看看