• hdu 2853(KM算法的巧妙利用)


    题目 要求最小改变多少条边,使得总的费用最大。

    以前遇到这种题目的时候,很多的时候都是看这条边是不是关键的边,经常就是去掉这条边看还满不满足条件。 但是这题不能用这种想法。

    这题的解法甚是巧妙,感觉可以应用在许多方面。

    由KM算法求解最优解的性质,在以不改变基本总权值的情况下(同时扩大K倍,最后除以K(k>n)),增大某些边( 只+1 ), 使得在算法运行结束后能够得到我们要的那些边的最大情况。

    这种思想必须掌握!

    Assignment

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


    Problem Description
    Last year a terrible earthquake attacked Sichuan province. About 300,000 PLA soldiers attended the rescue, also ALPCs. Our mission is to solve difficulty problems to optimization the assignment of troops. The assignment is measure by efficiency, which is an integer, and the larger the better.
    We have N companies of troops and M missions, M>=N. One company can get only one mission. One mission can be assigned to only one company. If company i takes mission j, we can get efficiency Eij. 
    We have a assignment plan already, and now we want to change some companies’ missions to make the total efficiency larger. And also we want to change as less companies as possible.
     
    Input
    For each test case, the first line contains two numbers N and M. N lines follow. Each contains M integers, representing Eij. The next line contains N integers. The first one represents the mission number that company 1 takes, and so on.
    1<=N<=M<=50, 1<Eij<=10000.
    Your program should process to the end of file.
     
    Output
    For each the case print two integers X and Y. X represents the number of companies whose mission had been changed. Y represents the maximum total efficiency can be increased after changing.
     
    Sample Input
    3 3 2 1 3 3 2 4 1 26 2 2 1 3 2 3 1 2 3 1 2 3 1 2
     
    Sample Output
    2 26 1 2
     
    Source
     
    Recommend
    gaojie
     
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    using namespace std;
    #define N 55
    #define INF 0x3fffffff
    
    int g[N][N];
    int n,m;
    int wx[N],wy[N];
    int save[N];
    int mark[N];
    int markx[N],marky[N];
    int pre[N];
    
    int dfs(int s) 
    {
        markx[s]=1;
        for(int i=1;i<=m;i++)
        {
            if(wx[s]+wy[i]-g[s][i] < save[i]) save[i]=wx[s]+wy[i]-g[s][i];
            if( mark[i]==1 || wx[s]+wy[i]!=g[s][i] ) continue;
            mark[i]=1;
            marky[i]=1;
            if(pre[i]==-1||dfs(pre[i]))
            {
                pre[i]=s;
                return 1;
            }
        }
        return 0;
    }
    
    int KM()
    {
        memset(wx,0,sizeof(wx));
        memset(wy,0,sizeof(wy));
        memset(pre,-1,sizeof(pre));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                wx[i]=max(wx[i],g[i][j]);
        for(int i=1;i<=n;i++)
        {
            while(1)
            {
                for(int j=1;j<=m;j++)
                    save[j]=INF;
                memset(markx,0,sizeof(markx));
                memset(marky,0,sizeof(marky));
                memset(mark,0,sizeof(mark));
                if(dfs(i)==1) break;
                int mi=INF;
                for(int j=1;j<=m;j++)
                    if(marky[j]==0&&save[j]<mi) mi=save[j];
                for(int j=1;j<=n;j++)
                    if(markx[j]==1) wx[j]-=mi;
                for(int j=1;j<=m;j++)
                    if(marky[j]==1) wy[j]+=mi;
            }
        }
        int sum=0;
        for(int i=1;i<=m;i++)
            if(pre[i]!=-1)    sum+=g[pre[i]][i];
        return sum;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(g,0,sizeof(g));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                {
                    scanf("%d",&g[i][j]);
                    g[i][j]*=100;
                }
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                int tmp;
                scanf("%d",&tmp);
                sum+=g[i][tmp]/100;
                g[i][tmp]++;
            }
            int ans=KM();
            printf("%d %d\n",n-ans%100,ans/100-sum);
        }
        return 0;
    }
  • 相关阅读:
    Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-C. Plasticine zebra
    牛客网-小白月赛6-J-洋灰三角
    树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花
    BZOJ-4318-OSU!期望DP
    Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-D- Array Restoration
    Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-C-Bracket Subsequence
    Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-A-Single Wildcard Pattern Matching
    Codeforces Round #503 (by SIS, Div. 2)-C. Elections
    百度之星-day1-1003-度度熊剪纸条
    百度之星-day2-1004-二分答案
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/3063094.html
Copyright © 2020-2023  润新知