LA4043二分图最佳匹配(注意建模)

 1 /*LA4043
 2 1<=n<=100
 3 给定两个集合A,B,每个集合的n个元素的坐标,以欧几里得距离为权值。
 4 求一个A到B的一一映射,每一对相互连线,使得,没有任何两条线是相交的。
 5 
 6 这道题有个特解:A和B的最佳匹配(使负的权值和最大),因为两条交叉的线,能换成两条不交叉的,从而增大负权值和。
 7 */
 8 #include <cmath>
 9 #include <algorithm>
10 #include <stdlib.h>
11 #include <iostream>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stack>
15 #include <set>
16 #include <map>
17 #include <vector>
18 #define typed double
19 #define INF 1<<30
20 #define maxn 110
21 #define eps 1e-6
22 using namespace std;
23 int n;
24 typed W[maxn][maxn];
25 typed Lx[maxn],Ly[maxn];
26 int lef[maxn];
27 bool S[maxn],T[maxn];
28 
29 bool match(int i){
30     S[i]=true;
31     for(int j=1;j<=n;j++) if (fabs(Lx[i]+Ly[j]-W[i][j])<eps && !T[j]){
32         T[j]=true;
33         if (!lef[j] || match(lef[j])){
34             lef[j]=i;
35             return true;
36         }
37     }
38     return false;
39 }
40 
41 void update(){
42     typed a=INF;
43     for(int i=1;i<=n;i++) if(S[i]){
44         for(int j=1;j<=n;j++) if(!T[j])
45             a=min(a,Lx[i]+Ly[j]-W[i][j]);
46     }
47     for(int i=1;i<=n;i++){
48         if (S[i]) Lx[i]-=a;
49         if (T[i]) Ly[i]+=a;
50     }
51 }
52 void KM(){
53     for(int i=1;i<=n;i++){
54         lef[i]=Lx[i]=Ly[i]=0;
55         for(int j=1;j<=n;j++){
56             Lx[i]=max(Lx[i],W[i][j]);
57         }
58     }
59     for(int i=1;i<=n;i++){
60         for(;;){
61             for(int j=1;j<=n;j++) S[j]=T[j]=false;
62             if (match(i)) break;else update();
63         }
64     }
65 }
66 typed AX[maxn],AY[maxn];
67 typed BX[maxn],BY[maxn];
68 double dis(int u,int v){
69     double ans=-sqrt((BX[u]-AX[v])*(BX[u]-AX[v])+(BY[u]-AY[v])*(BY[u]-AY[v]));
70     return ans;
71 }
72 void read(){
73     for(int i=1;i<=n;i++) scanf("%lf%lf",&AX[i],&AY[i]);
74     for(int i=1;i<=n;i++) scanf("%lf%lf",&BX[i],&BY[i]);
75     for(int i=1;i<=n;i++)
76     for(int j=1;j<=n;j++)
77     W[i][j]=dis(i,j);
78 }
79 int t=0;
80 int main(){
81     while(cin>>n){
82         t++;
83         read();
84         KM();
85         if (t>1) printf("
");
86         for(int i=1;i<=n;i++) printf("%d
",lef[i]);
87     }
88     return 0;
89 }
原文地址:https://www.cnblogs.com/little-w/p/3643969.html