Assignment
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1068 Accepted Submission(s): 551
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
2009 Multi-University Training Contest 5 - Host
by NUDT
Recommend
gaojie | We have carefully selected several similar problems for you: 2855 2854 2856 2857 2858
题意:n个公司m个任务,每个公司只接受一个任务,每个任务只被一个公司接受,每个公司i接受任务j的做事效率为g[i][j],现在已经分配好了,问怎样改变任务分配可以让效率最大,求出要改动的公司数目和增加的效率。
思路:与hdu3315相似,hdu 3315;若点数为N,则把每条边的权值扩大x倍(x>N),若是原有匹配,则再把权值加1。最后KM算法求出ans,则最大权值之和=ans/x,没有被改动的=ans%x。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; /* KM算法 O(nx*nx*ny) 求最大权匹配(最佳匹配) 若求最小权匹配,可将权值取相反数,结果取相反数 点的标号从0开始 */ const int N=110; int nx,ny; //两边的点数 int g[N][N]; //二分图描述,g赋初值为-INF int linker[N],lx[N],ly[N]; //y 中各点匹配状态,x,y中的点的标号 int slack[N]; bool visx[N],visy[N]; bool flag; bool DFS(int x) { visx[x]=true; for (int y=0;y<ny;y++) { if (visy[y]) continue; int tmp=lx[x]+ly[y]-g[x][y]; if (tmp==0) { visy[y]=true; if (linker[y]==-1||DFS(linker[y])) { linker[y]=x; return true; } } else if (slack[y]>tmp) slack[y]=tmp; } return false; } int KM() { flag=true; memset(linker,-1,sizeof(linker)); memset(ly,0,sizeof(ly)); for (int i=0;i<nx;i++) //赋初值,lx置为最大值 { lx[i]=-INF; for (int j=0;j<ny;j++) { if (g[i][j]>lx[i]) lx[i]=g[i][j]; } } for (int x=0;x<nx;x++) { for (int i=0;i<ny;i++) slack[i]=INF; while (true) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if (DFS(x)) break; int d=INF; for (int i=0;i<ny;i++) if (!visy[i]&&d>slack[i]) d=slack[i]; for (int i=0;i<nx;i++) if (visx[i]) lx[i]-=d; for (int i=0;i<ny;i++) { if (visy[i]) ly[i]+=d; else slack[i]-=d; } } } int res=0; for (int i=0;i<ny;i++) { if (linker[i]==-1||g[linker[i]][i]<=-INF) //有的点不能匹配的话return-1 { flag=false; continue; } res+=g[linker[i]][i]; } return res; } //记得nx和ny初始化!!!!!!!! int n,m; int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin); #endif int i,j,x; while (~sff(n,m)) { nx=n; ny=m; int sum=0; for (i=0;i<n;i++) for (j=0;j<m;j++) { sf(x); g[i][j]=x*100; } for (i=0;i<n;i++) { sf(x);x--; sum+=g[i][x]; g[i][x]++; } int ans=KM(); printf("%d %d\n",n-ans%100,ans/100-sum/100); } return 0; } /* 3 3 2 1 3 3 2 4 1 26 2 2 1 3 2 3 1 2 3 1 2 3 1 2 */
版权声明:本文为博主原创文章,未经博主允许不得转载。