• 【最大权森林/Kruskal】POJ3723-Conscription


    【题目大意】

    招募m+n个人每人需要花费$10000,给出一些关系,征募某个人的费用是原价-已招募人中和他亲密值的最大值,求最小费用。

    【思路】

    人与人之间的亲密值越大,花费越少,即求出最大权森林,可以用最小(大)生成树的思路来解决。按亲密值由大到小排序,对于每一个关系,判断两人是否在一个集合中,在则跳过,否则从总钱数中减去亲密值,合并两个集合。注意:人的编号是从0开始的!

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int MAXN=100000+5;
     6 struct Rec
     7 {
     8     int ori,des,len;
     9     bool operator < (const Rec &x) const
    10     {
    11         return len>x.len;
    12     }
    13 }edge[MAXN*5];
    14 int par[MAXN*2],height[MAXN*2];
    15 int n,m,r;
    16 /*n代表女兵,m代表男兵,这里不需要用到二分图;r代表关系数*/
    17 int ans;
    18 
    19 void initset()
    20 {
    21     for (int i=0;i<(n+m);i++)
    22     {
    23         par[i]=i;
    24         height[i]=0;
    25     }
    26 }
    27 
    28 int find(int x)
    29 {
    30     int r=x,temp;
    31     while (par[r]!=r) r=par[r];
    32     while (x!=r)
    33     {
    34         temp=par[x];
    35         par[x]=r;
    36         x=temp;
    37     }
    38     return (r);
    39 }
    40 
    41 void unionset(int fa,int fb)
    42 {
    43     if (height[fa]>=height[fb])
    44     {
    45         par[fb]=fa;
    46         if (height[fa]==height[fb]) height[fa]++;
    47     }
    48     else 
    49         par[fa]=fb;
    50 }
    51 
    52 int main()
    53 {
    54     int kase;
    55     scanf("%d",&kase);
    56     for (int cases=0;cases<kase;cases++)
    57     {
    58         scanf("%d%d%d",&n,&m,&r);
    59         int ans=10000*(m+n);
    60         for (int i=0;i<r;i++)
    61         {
    62             int u,v,w;
    63             scanf("%d%d%d",&u,&v,&w);
    64             edge[i].ori=u;
    65             edge[i].des=v+n;
    66             edge[i].len=w;
    67         }
    68         sort(edge,edge+r);
    69         initset();
    70         for (int i=0;i<r;i++)
    71         {
    72             int fa=find(edge[i].ori);
    73             int fb=find(edge[i].des);
    74             if (fa!=fb)
    75             {
    76                 unionset(fa,fb);
    77                 ans-=edge[i].len;
    78             }
    79         }
    80         cout<<ans<<endl;
    81     }
    82     system("pause");
    83     return 0;
    84 }
  • 相关阅读:
    文学、哲学段子
    文学、哲学段子
    js技术要点---JS 获取网页源代码
    泛型类,泛型方法,泛型委托的定义方法
    数组元素的逆序数
    stm32 ARM中的RO、RW和ZI DATA
    poj 3040 Allowance 贪心
    schedule()函数的调用时机(周期性调度)
    以JTextPanel为例Swing的鼠标事件详解
    实习生面试总结
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/4708108.html
Copyright © 2020-2023  润新知