zoukankan      html  css  js  c++  java
  • 二分图相关知识

    hdu2255:奔小康赚大钱(二分图带权最大匹配)

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 17911    Accepted Submission(s): 7534


    Problem Description
    传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
    这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
    另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
     
    Input
    输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。
     
    Output
    请对每组数据输出最大的收入值,每组的输出占一行。

     
    Sample Input
    2 100 10 15 23
     
    Sample Output
    123
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  2063 1068 3360 1083 2444
     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    const int MAXN = 305;
    const int INF = 0x3f3f3f3f;
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    
    int N;
    
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < N; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < N; ++i)
            res += love[ match[i] ][i];
    
        return res;
    }
    
    int main()
    {
        while (~scanf("%d", &N)) {
    
            for (int i = 0; i < N; ++i)
                for (int j = 0; j < N; ++j)
                    scanf("%d", &love[i][j]);
    
            printf("%d
    ", KM());
        }
        return 0;
    }        

    Vasya and Endless Credits

    CodeForces - 1107F
     

    Vasya wants to buy himself a nice new car. Unfortunately, he lacks some money. Currently he has exactly 0 burles.

    However, the local bank has n

    credit offers. Each offer can be described with three numbers ai, bi and ki. Offers are numbered from 1 to n. If Vasya takes the i-th offer, then the bank gives him ai burles at the beginning of the month and then Vasya pays bank bi burles at the end of each month for the next ki

    months (including the month he activated the offer). Vasya can take the offers any order he wants.

    Each month Vasya can take no more than one credit offer. Also each credit offer can not be used more than once. Several credits can be active at the same time. It implies that Vasya pays bank the sum of bi

    over all the i

     

    of active credits at the end of each month.

    Vasya wants to buy a car in the middle of some month. He just takes all the money he currently has and buys the car of that exact price.

    Vasya don't really care what he'll have to pay the bank back after he buys a car. He just goes out of the country on his car so that the bank can't find him anymore.

    What is the maximum price that car can have?

    Input

    The first line contains one integer n

    (1n500

    ) — the number of credit offers.

    Each of the next n

    lines contains three integers ai, bi and ki (1ai,bi,ki109

    ).

    Output

    Print one integer — the maximum price of the car.

    Examples
    Input
    4
    10 9 2
    20 33 1
    30 115 1
    5 3 2
    
    Output
    32
    
    Input
    3
    40 1 2
    1000 1100 5
    300 2 1
    
    Output
    1337
    
    Note

    In the first example, the following sequence of offers taken is optimal: 4

    3.

    The amount of burles Vasya has changes the following way: 5

    32 -86

    .... He takes the money he has in the middle of the second month (32 burles) and buys the car.

    The negative amount of money means that Vasya has to pay the bank that amount of burles.

    In the second example, the following sequence of offers taken is optimal: 3

    1

    2.

    The amount of burles Vasya has changes the following way: 0

    300 338 1337 236 -866 ....

     

     

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    typedef long long ll;
    using namespace std;
    const int MAXN = 605;
    const ll INF = 0x3f3f3f3f3f3f3f;
    
    ll love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    ll ex_girl[MAXN];      // 每个妹子的期望值
    ll ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    ll slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    
    int N;
    
    ll max(ll a,ll b){
        return a>b?a:b;
    }
    
    ll min(ll a,ll b){
        return a<b?a:b;
    }
    
    bool dfs(ll girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < N; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            ll gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    ll KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                ll d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的好感度的和
        ll res = 0;
        for (int i = 0; i < N; ++i)
            res += love[ match[i] ][i];
    
        return res;
    }
    
    int main()
    {
        while (~scanf("%d", &N)) {
            for(int i=0;i<N;i++){
                ll ta,tb,tc;
                scanf("%lld%lld%lld",&ta,&tb,&tc);            
                for(int j=0;j<N;j++){
                    ll tem=max(ta-(ll)tb*min(tc,j),0);
                        love[i][j]=tem;
                } 
            }
            cout<<KM()<<endl;
        }
        return 0;
    }        

    Going Home

    HDU - 1533(二分图带权最小匹配)
     
     
    On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.

    Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point.

    You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

    InputThere are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
    OutputFor each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.
    Sample Input
    2 2
    .m
    H.
    5 5
    HH..m
    .....
    .....
    .....
    mm..H
    7 8
    ...H....
    ...H....
    ...H....
    mmmHmmmm
    ...H....
    ...H....
    ...H....
    0 0
    Sample Output
    2
    10
    28
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include<math.h>
    
    using namespace std;
    const int MAXN = 305;
    const int INF = 0x3f3f3f3f;
    
    struct node{
        int x;int y;
    }ren[1009],fz[1009];
    
    
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    
    int N; //(注意赋值,不然跑不出来)
    
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < N; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < N; ++i)
            res += love[ match[i] ][i];
    
        return res;
    }
    
    char s[1009][1009];
    
    
    int main()
    {
        int n,m; 
        while(~scanf("%d%d",&n,&m)){
            if(n==0&&m==0) break;
            for(int i=1;i<=n;i++)
                scanf("%s",s[i]);
            int ctren,ctfz;
            ctren=ctfz=0;
            for(int i=1;i<=n;i++){
                for(int j=0;j<m;j++){
                    if(s[i][j]=='m'){
                        ren[ctren].x=i,ren[ctren++].y=j;
                    }
                    else if(s[i][j]=='H'){
                        fz[ctfz].x=i,fz[ctfz++].y=j;
                    } 
                }
            }
            for(int i=0;i<ctren;i++){
                for(int j=0;j<ctfz;j++){
                    love[i][j]=-(abs(ren[i].x-fz[j].x)+abs(ren[i].y-fz[j].y));
                    //cout<<love[i][j]<<endl;
                }
            }
            N=ctfz;//注意
            cout<<-KM()<<endl;        
            
        }
    
        return 0;
    }       
     

    Special Fish

    HDU - 3395
     
    There is a kind of special fish in the East Lake where is closed to campus of Wuhan University. It’s hard to say which gender of those fish are, because every fish believes itself as a male, and it may attack one of some other fish who is believed to be female by it.
    A fish will spawn after it has been attacked. Each fish can attack one other fish and can only be attacked once. No matter a fish is attacked or not, it can still try to attack another fish which is believed to be female by it.
    There is a value we assigned to each fish and the spawns that two fish spawned also have a value which can be calculated by XOR operator through the value of its parents.
    We want to know the maximum possibility of the sum of the spawns.

    InputThe input consists of multiply test cases. The first line of each test case contains an integer n (0 < n <= 100), which is the number of the fish. The next line consists of n integers, indicating the value (0 < value <= 100) of each fish. The next n lines, each line contains n integers, represent a 01 matrix. The i-th fish believes the j-th fish is female if and only if the value in row i and column j if 1.
    The last test case is followed by a zero, which means the end of the input.OutputOutput the value for each test in a single line.Sample Input
    3
    1 2 3
    011
    101
    110
    0
    Sample Output
    6


    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    const int MAXN = 305;
    const int INF = 0x3f3f3f3f;
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    int v[MAXN];
    char s[MAXN][MAXN];
    
    int N;
    
    
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < N; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {//注意这儿j是1,修改时别改错了 
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < N; ++i)
            res += love[ match[i] ][i];
    
        return res;
    }
    
    int main()
    {
        while (~scanf("%d", &N)) {
        if(N==0) break;
        for(int i=0;i<N;i++)
            scanf("%d",&v[i]);
        for(int i=0;i<N;i++) scanf("%s",s[i]); 
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < N; ++j){
                if(s[i][j]=='1'){
                    love[i][j]=(v[i]^v[j]);
                }
                else love[i][j]=0;
            }
        printf("%d
    ",KM());
        }
        return 0;
    }        

    无法攻击的设置为0即可

    Chocolate

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1068    Accepted Submission(s): 535


    Problem Description
    Lethe loves eating chocolates very much. In Lethe's birthday, her good friend echo brings N boxes to her, and makes the boxes on the circle. Furthermore, echo tells Lethe that there are many chocolates in the boxes, but the total number of chocolates doesn't exceed N. Also, echo wants Lethe to displace the chocolates in such a way that in each box remains no more than one chocolate. In one move she can shift one chocolate from current box to its neighboring box. (Each box has two neighboring boxes). Can you tell Lethe the minimum number of move to achieve this goal?
     
    Input
    There are multi-cases (The total number of cases won't exceed 20). First line is an integer N(1<=N<=500), the total number of boxes. Then N lines follow, each line includes a number, indicates the number of chocolates in the box.
     
    Output
    Output the minimum number of move.
     
    Sample Input
    10 1 3 3 0 0 2 0 0 0 0
     
    Sample Output
    9
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  2286 2283 2288 2287 2285
     
     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    const int MAXN = 605;
    const int INF = 0x3f3f3f3f;
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    int v1[MAXN];
    int v2[MAXN];
    char s[MAXN][MAXN];
    
    int N,M;
    
    
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < M; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < M; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
        //    memset(slack,INF,sizeof(slack));
            fill(slack, slack + M, INF);    // 因为要取最小值 初始化为无穷大(如果不是1对1记得更改)
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < M; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
                }
                    // 所有访问过的男生增加期望值
                for(int j=0;j<M;j++){
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;                
                }      
            }
        }
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < M; ++i){
            if(match[i]!=-1)  res += love[ match[i] ][i];
        }
            
    
        return res;
    }
    
    int main()
    {
        int ct;
        while (~scanf("%d", &ct)) {
            N=M=0;
            int tem;
            for(int i=0;i<ct;i++){
                scanf("%d",&tem);
                if(tem==0){
                    v2[M++]=i;
                }
                else if(tem!=1){
                    tem--;
                    while(tem--){
                        v1[N++]=i;
                    }
                }
            }
            for(int i=0;i<N;i++){
                for(int j=0;j<M;j++){
                    int maxn=v1[i];
                    int minn=v2[j];
                    if(maxn<minn) swap(maxn,minn);
                    love[i][j]=-min(maxn-minn,ct-maxn+minn);
                }
            }         
        printf("%d
    ",-KM());
        }
        return 0;
    }        

    slack数组记得改,卡了好长时间好难受

    One fihgt one

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3190    Accepted Submission(s): 1028


    Problem Description
    Lv Bu and his soldiers are facing a cruel war——Cao Cao had his best generals just miles away.

    There’s little time , but Lv Bu is unaware of how to arrange his warriors , what he know is that he have n brave generals while Cao Cao has m , and he has k fights to choose from , he’d like to make all his n warriors participate in the battle but get the least injuries . Lv Bu is happy because there is always a good solution . So , now is your task to tell Lv Bu the least injuries his troop would get.
    No one could take part in two fights.
     
    Input
    Multiple cases. For each case ,there are three integers in the first line , namely n,m (1<=n<=m<=200)and k (n<=k<=m*n).
    The next k lines are the information about k possible fights , for each line are two strings (no more than 20 characters ) and an integer. The first string indicates Lv Bu’s general and the second , of course , Cao Cao’s , and the integer is the injury Lv Bu’s general would get if this fight were chosen.
     
    Output
    One integer , the least injuries Lv Bu’s generals would get.
     
    Sample Input
    2 3 5 LvBu ZhangFei 6 LvBu GuanYu 5 LvBu XuChu 4 ZhangLiao ZhangFei 8 ZhangLiao XuChu 3
     
    Sample Output
    8
     
    Author
    shǎ崽
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  2811 2816 2809 2810 2812 
     
     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include<map>
    #include<algorithm>
    using namespace std;
    
    map<string,int> mp1;
    map<string,int> mp2;
    const int MAXN = 605;
    const int INF = 0x3f3f3f3f;
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    int N,M,k;
    
    
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; boy < M; ++boy) {
    
            if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
    
            int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
    
            if (gap == 0) {  // 如果符合要求
                vis_boy[boy] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < M; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
        //    memset(slack,INF,sizeof(slack));
            fill(slack, slack + M, INF);    // 因为要取最小值 初始化为无穷大(如果不是1对1记得更改)
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < M; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
                }
                    // 所有访问过的男生增加期望值
                for(int j=0;j<M;j++){
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;                
                }      
            }
        }
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < M; ++i){
            if(match[i]!=-1)  res += love[ match[i] ][i];
        }
            
    
        return res;
    }
    
    int main()
    {
        int ct;
        int va;
        while (~scanf("%d%d%d", &N,&M,&k)) {
            int c1=1,c2=1;
            mp1.clear();
            mp2.clear();
            memset(love,-INF,sizeof(love));
            for(int i=1;i<=k;i++){
                char s1[40],s2[40];
                scanf("%s%s",s1,s2);
                if(mp1[s1]==0) mp1[s1]=c1++;
                if(mp2[s2]==0) mp2[s2]=c2++;
                scanf("%d",&va);
                love[mp1[s1]-1][mp2[s2]-1]=-va;
            }
            printf("%d
    ",-KM());
        }
        return 0;
    }        

    慎用string,t了

  • 相关阅读:
    基于Delphi的三层数据库系统的实现方法
    用数据表创建树_delphi教程
    多层数据库开发十三:剖析几个数据库应用程序
    多层数据库开发十二:使用数据控件
    多层数据库开发九:查询数据库
    第十一章 TClientDataSet
    用python做线性规划
    Python-sympy科学计算与数据处理(求极限及其它功能)
    Python-sympy科学计算与数据处理(方程,微分,微分方程,积分)
    Python-sympy科学计算与数据处理(数学表达式)
  • 原文地址:https://www.cnblogs.com/ellery/p/11686187.html
Copyright © 2011-2022 走看看