poj3565 (maximum weight perfect match)

Posted by zsedc on Sat, 19 Feb 2022 11:14:41 +0100

Meaning: let n ants to an apple tree, and give the corresponding coordinates of N ants and N apple trees. To calculate the weight is to calculate the distance between coordinate points, and it is required to calculate the minimum distance!
Idea: use the maximum weight perfect matching problem, but now the problem is to find the minimum weight. You can take the inverse distance between the obtained coordinates. After taking the inverse, finding the maximum weight is the minimum distance.

Maximum weight perfect matching: the maximum matching of bipartite graph is to find the maximum number of matches, using Hungarian algorithm. When the connected edges have weights, it is necessary to find the scheme with the largest weight sum after matching, and ensure that the points in set A can be matched with the points in set B. At this point, the problem is transformed into bipartite graph maximum weight perfect matching.

The core of KM algorithm is: add the top mark for each point, and process the maximum number of matches with Hungarian algorithm under the limitation of the top mark. If the maximum number of matches = n, the optimal solution is reached and the output is. Otherwise modify
The top mark is processed by Hungarian algorithm, and so on.

Let the two-part point sets of bipartite graph be X={X1,X2,..., Xn}X={X1,X2,..., Xn} and Y={Y1,Y2,..., Ym}Y={Y1,Y2,..., Ym}, ⟨ Xi,Yj ⟩ Xi,Yj ⟩ Xi and wij ⟩ respectively
Assign point weights {AI}, {Bi}, {AI}, {Bi} to the two-part point sets respectively, so that the generated subgraph of the edge of Ai+Bj ⩾ wij is called equal subgraph. Then the perfect matching of equal subgraphs is the maximum weight matching. We need to select appropriate weights to make equal subgraphs match perfectly.
Algorithm steps:
1. If it is successful (the augmentation track is found), the augmentation of this point is completed and the augmentation of the next point is entered
2. If it fails (the augmented track is not found), it is necessary to change the label of some points to increase the number of feasible edges in the figure.
The operation is as follows: subtract a constant d from the labels of all X-square points in the augmented track (that is, traverse in the augmented process), and add a constant d to the labels of all Y-square points in the augmented track

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#include<iomanip>
#include<cstdio>
#define esp 1e-6
using namespace std;
const int maxx=105;
const int maxn=10005;
const int inf=0x3f3f3f3f;
double lx[maxx],ly[maxx];
int visx[maxx],visy[maxx];
double w[maxx][maxx];
int linker[maxx];
double slack[maxx];
int n,m,k;
struct node{
	double x,y;
}num[maxx],e[maxx];
double Dist(node a,node b){
	double x=a.x-b.x;
	double y=a.y-b.y;
	return sqrt(x*x+y*y);
}
void init(){
	memset(linker,0,sizeof(linker));
	memset(w,0,sizeof(w));
}
int Find(int x){
	visx[x]=1;
	for(int y=1;y<=n;y++){
		if(visy[y]==0){
			double temp=abs(lx[x]+ly[y]-w[x][y]);
			if(temp<=esp){
				visy[y]=1;
				if(linker[y]==0||Find(linker[y])){
					linker[y]=x;
					return 1;
				}
			}else{
				slack[y]=min(slack[y],temp);
			}
		}
	}
	return 0;
}
void KM(){
	memset(ly,0,sizeof(ly));
	for(int i=1;i<=n;i++){
		lx[i]=-inf;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(lx[i]<w[i][j]){
				lx[i]=w[i][j];
			}
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			slack[i]=inf;
		}
		while(true){
			memset(visx,0,sizeof(visx));
			memset(visy,0,sizeof(visy));
			if(Find(k))break;
			double d=inf;
			for(int i=1;i<=n;i++){
				if(visy[i]==0){
					d=min(d,slack[i]);
				}
			}
			for(int i=1;i<=n;i++){
				if(visx[i]==1)lx[i]-=d;
				if(visy[i]==1)ly[i]+=d;
				else{
					slack[i]-=d;
				}
			}
		}
	}
}
int main(){
	while(scanf("%d",&n)!=EOF){
		init();
		for(int i=1;i<=n;i++){
			scanf("%lf %lf",&num[i].x,&num[i].y);
		}
		for(int i=1;i<=n;i++){
			scanf("%lf %lf",&e[i].x,&e[i].y);
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				w[i][j]=-1.0*Dist(num[i],e[j]);
			}
		}
		KM();
		int t[maxx];
		memset(t,0,sizeof(t));
		for(int i=1;i<=n;i++){
			t[linker[i]]=i;
		}
		for(int i=1;i<=n;i++){
			cout<<t[i]<<endl;
		}
	}
	return 0;
}

Topics: Algorithm data structure