zoukankan      html  css  js  c++  java
  • 自出题,写题解《招募士兵》

    招募士兵
    (conscription.pas/c/cpp)
    【问题描述】
    小W拥有一个国家,现在他希望建立一支军队来保护他的国家。他选中了N个女孩和M个男孩希望招募他们成为他的士兵。在没有任何先决条件的情况下,他招募一个士兵需要花费10000RMB。现在小W可以利用这些人之间的关系来减少他的花费。如果女孩X和男孩Y存在有一个关系值D(两人之间可能有多个关系值),而且她们之中有一个人被招募了。那么小W可以在招募另一个人的时候减少D的花费(实际10000-D的费用)。
    现在给你这些男孩女孩之间的关系,希望你告诉小W告诉他招募所有人的最少花费。
    注意:招募某一个人时,只能利用一个关系。
    【输入】
    输入文件conscription.in中文件第一行包含三个整数N,M,R。表示N个女孩,M个男孩与R条关系。
    接下来R行,每行包含三个整数Xi,Yi和Di,表示女孩Xi和男孩Yi有Di的关系。
    【输出】
    conscription.out中只有一行一个数,为最小费用。
    【输出样例】
    5 5 8
    4 3 6831
    1 3 4583
    0 0 6592
    0 1 3063
    3 3 4975
    1 3 2049
    4 2 2104
    2 2 781
    【输出样例】
    71071

    【数据说明】
    100%的数据:1<=N, M <=100000,0 <=R <=200,000,0 < di < 10000

    本题烤驴到一个并查集的问题,然后,我们把他可以减少的价钱排个序,再一个一个地去并起来,如果他们的father一样,就不可以并起来,这样子就能解决问题。

    参考程序:

    type
            new=record
                    x:longint;
                    y:longint;
                    r:longint;
                    bz:boolean;
            end;
    
    var
            i,j,k,l,n,m,r,v,x,y:longint;
            ans:int64;
            f:array[0..200000] of longint;
            a:array[1..200000] of new;
            bz:boolean;
    procedure qs(l,r:longint);
    var
            i,j,m:longint;
            t:new;
    begin
            i:=l;
            j:=r;
            m:=a[(l+r) div 2].r;
            repeat
                    while a[i].r>m do inc(i);
                    while a[j].r<m do dec(j);
                    if i<=j then
                    begin
                            t:=a[i];
                            a[i]:=a[j];
                            a[j]:=t;
                            inc(i);
                            dec(j);
                    end;
            until i>j;
            if l<j then qs(l,j);
            if i<r then qs(i,r);
    end;
    function zs(t:longint):longint;
    var
            i,j,k,l:longint;
    begin
            l:=t;
            while f[t]<>t do
            begin
                    t:=f[t];
            end;
            while f[l]<>t do
            begin
                    j:=f[l];
                    f[l]:=t;
                    l:=j;
            end;
            zs:=t;
    
    end;
    
    begin
            readln(n,m,r);
            for i:=1 to r do
            begin
                    readln(a[i].x,a[i].y,a[i].r);
                    a[i].y:=a[i].y+n;
            end;
            for i:=1 to n+m do f[i]:=i;
            qs(1,r);
            ans:=0;
            v:=0;
    
            for i:=1 to r do
            begin
                    if zs(a[i].x)<>zs(a[i].y) then
                    begin
                            x:=zs(a[i].x);
                            y:=zs(a[i].y);
                            f[x]:=y;
                            a[i].bz:=true;
                            ans:=ans+(10000-a[i].r);
                            inc(v);
                    end;
            end;
            writeln(ans+(n+m-v)*10000);
    end.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    Python动态展示遗传算法求解TSP旅行商问题
    MOEAD算法中均匀权向量的实现---Python
    HDU 5294 多校第一场1007题 最短路+最小割
    POJ 3261 Milk Patterns sa+二分
    HDU 4292 FOOD 2012 ACM/ICPC Asia Regional Chengdu Online
    CodeForces 201A Clear Symmetry
    POJ 1679 The Unique MST 确定MST是否唯一
    POJ 3268 Silver Cow Party 最短路 基础题
    POJ 2139 SIx Degrees of Cowvin Bacon 最短路 水題
    POJ2229 Sumsets 基礎DP
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148462.html
Copyright © 2011-2022 走看看