Topic link: http://acm.hdu.edu.cn/showproblem.php?pid=2255
Problem Description
Legend has it that there was a very wealthy village in a faraway place, and one day, the head of the village decided to reform the system: redistribute houses.
This is a major event, and it is related to the housing issue of the people. There are a total of n rooms in the village, and there are just n families of people. Considering that each family must have a house (if there are people who do not have a house to live in, it is easy to cause instability), each family must be allocated a house and can only get one house. house.
On the other hand, the village head and other village leaders want to get the maximum benefit, so that the institutions in the village will have money. Since the common people are relatively wealthy, they can pay a certain price for each house within their economic range. , For example, if there are 3 houses, an ordinary family can pay 100,000 yuan for the first house, 20,000 yuan for the second house, and 200,000 yuan for the third house (of course within their economic scope). Now the problem is the village How can the leaders allocate houses to maximize their income. (Even if the villagers have the money to buy a house, they may not be able to buy it, it depends on the allocation of the village leaders).
This is a major event, and it is related to the housing issue of the people. There are a total of n rooms in the village, and there are just n families of people. Considering that each family must have a house (if there are people who do not have a house to live in, it is easy to cause instability), each family must be allocated a house and can only get one house. house.
On the other hand, the village head and other village leaders want to get the maximum benefit, so that the institutions in the village will have money. Since the common people are relatively wealthy, they can pay a certain price for each house within their economic range. , For example, if there are 3 houses, an ordinary family can pay 100,000 yuan for the first house, 20,000 yuan for the second house, and 200,000 yuan for the third house (of course within their economic scope). Now the problem is the village How can the leaders allocate houses to maximize their income. (Even if the villagers have the money to buy a house, they may not be able to buy it, it depends on the allocation of the village leaders).
Input
The input data contains multiple sets of test cases. The first line of each set of data is input n, which represents the number of houses (also the number of ordinary people's homes), followed by n lines, and the n numbers in each line represent the ith village name versus the jth The price of the room (n<=300).
Output
Please output the maximum income value for each group of data, and the output of each group occupies one line.
Sample Input
2
100 10
15 23
Sample Output
123
Topic idea: maximum matching of weighted bipartite graph, KM algorithm bare question
Code:
#include<cstdio> #include<cmath> #include<cstring> #include<string> #include<cstdlib> #include<algorithm> #include<iostream> #include<queue> #include<stack> #include<map> using namespace std; #define FOU(i,x,y) for(int i=x;i<=y;i++) #define FOD(i,x,y) for(int i=x;i>=y;i--) #define MEM(a,val) memset(a,val,sizeof(a)) #define PI acos(-1.0) const double EXP = 1e-9; typedef long long ll; typedef unsigned long long ull; const int INF = 0x3f3f3f3f; const ll MINF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; const int N = 310; int nx,ny; //points on both sides int g[N][N]; //Bipartite graph description, g[i][j] represents the weight between i and j, the maximum matching is initialized to -INF to indicate infinite, and the minimum matching is similarly initialized to INF int linker[N]; //record which x of the y link, -1 means none int lx[N],ly[N];//The matching status of each point in y, the point label in x, y int slack[N]; //slack is the modifier bool visx[N],visy[N]; bool DFS(int x) { visx[x] = true; for(int y = 0; y < ny; y++) { if(visy[y])continue; //Continue after use int tmp = lx[x] + ly[y] - g[x][y]; if(tmp == 0) // meet the matching requirements { 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 () { memset(linker,-1,sizeof(linker)); memset(ly,0,sizeof(ly)); //The expected value of the initial right side is all 0 for(int i = 0;i < nx;i++) { lx[i] = -INF; //The expected value on the left is the maximum edge weight for(int j = 0;j < ny;j++) if(g[i][j] > lx[i]) lx[i] = g[i][j]; } //Start to solve the left matching problem for(int x = 0;x < nx;x++) { for(int i = 0;i < ny;i++) slack[i] = INF; //Because the minimum value is taken, it is initialized to infinity while(true) { // The way to solve the home problem for the left is: if you can't find it, lower the expectation until you find it // Record whether the left and right sides have been tried to match in each round of matching memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(DFS(x)) //find a match, exit break; //Not found, lower expectations //minimum can reduce the expected value 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) res += g[linker[i]][i]; return res; } intmain() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); std::ios::sync_with_stdio(false); int n; while(~scanf("%d",&n)) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&g[i][j]); nx = ny = n; printf("%d\n",KM()); } return 0; }