HDU 2853 KM 改边最少

Assignment

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


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

题意:要求改变最少的匹配,得到最大权匹配。

解题思路:自己想没思路,看别人的思路,把所有的边权都乘以100,然后把原来的边权+1,求出最大匹配后对100取模就可以得到改变的最小量,好神奇。

代码:

 

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<limits.h>
using namespace std;
const int inf=INT_MAX;
const int maxn=300;
int sx[maxn],sy[maxn],lx[maxn],ly[maxn],weight[maxn][maxn],m,n,match[maxn],slack[maxn];
bool path(int u)
{
        sx[u]=1;
        for(int v=0;v<m;v++)
        {
                if(sy[v])continue;
                int tt=lx[u]+ly[v]-weight[u][v];
                if(tt==0)
                {
                        sy[v]=1;
                        if(match[v]==-1||path(match[v]))
                        {
                                match[v]=u;
                                return 1;
                        }
                }
                else if(slack[v]>tt)slack[v]=tt;
        }
        return 0;
}
int km()
{
        for(int i=0;i<n;i++)
        {
                lx[i]=-inf;
                for(int j=0;j<m;j++)
                if(lx[i]<weight[i][j])lx[i]=weight[i][j];
        }
        memset(match,-1,sizeof(match));
        memset(ly,0,sizeof(ly));
        for(int u=0;u<n;u++)
        while(1)
        {
                memset(sx,0,sizeof(sx));
                memset(sy,0,sizeof(sy));
                for(int i=0;i<m;i++)slack[i]=inf;
                if(path(u))break;
                int cnt=inf;
                for(int i=0;i<m;i++)if(!sy[i]&&slack[i]<cnt)cnt=slack[i];
               // if(cnt==0)break;
                for(int i=0;i<n;i++)if(sx[i])lx[i]-=cnt;
                for(int i=0;i<m;i++)if(sy[i])ly[i]+=cnt;else slack[i]-=cnt;
        }
        int ans=0;
        for(int i=0;i<m;i++)
        if(match[i]>=0)ans+=weight[match[i]][i];
        return ans;
}
int main()
{

       while(~scanf("%d%d",&n,&m))
       {
            for(int i=0;i<n;i++)for(int j=0;j<m;j++)scanf("%d",&weight[i][j]),weight[i][j]*=100;
            int pre=0,p;
            for(int i=0;i<n;i++)
                        {
                                scanf("%d",&p);p--;
                                pre+=weight[i][p];
                                weight[i][p]++;
                        }
                        int cost=km();
            printf("%d %d\n",n-cost%100,cost/100-pre/100);
       }
       return 0;
}

 

posted @ 2013-09-07 19:11  线性无关  阅读(101)  评论(0)    收藏  举报