洛谷3705 [SDOI2017] 新生舞会 【01分数规划】【KM算法】

题目分析:

裸题。怀疑$ O(n^4log{n}) $跑不过,考虑Edmonds-Karp优化。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn =  120;
 5 
 6 const double eps = 1e-7;
 7 
 8 int n;
 9 
10 int a[maxn][maxn],b[maxn][maxn];
11 
12 double lx[maxn],ly[maxn],c[maxn][maxn];
13 int inS[maxn],inT[maxn],Left[maxn];
14 double slack[maxn];
15 
16 void read(){
17     scanf("%d",&n);
18     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
19     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&b[i][j]);
20 }
21 
22 int match(int now){
23     inS[now] = 1;
24     for(int i=1;i<=n;i++){ 
25     if(inT[i]) continue;
26     if(lx[now]+ly[i] - c[now][i] <= eps){
27         inT[i] = 1;
28         if(!Left[i] || match(Left[i])){
29         Left[i] = now;
30         return true;
31         }
32     }else slack[i] = min(slack[i],lx[now]+ly[i]-c[now][i]);
33     }
34     return false;
35 }
36 
37 void update(){
38     double pp = 1e9;
39     for(int i=1;i<=n;i++) if(!inT[i]) pp = min(pp,slack[i]);
40     for(int i=1;i<=n;i++){
41     if(inS[i]) lx[i] -= pp;
42     if(inT[i]) ly[i] += pp;
43     else slack[i] -= pp;
44     }
45 }
46 
47 bool KM(double now){
48     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) c[i][j] = a[i][j]-now*b[i][j];
49     for(int i=1;i<=n;i++) {
50     lx[i] = -1E9,ly[i] = 0; Left[i] = 0;
51     for(int j=1;j<=n;j++) lx[i] = max(lx[i],c[i][j]);
52     }
53     for(int i=1;i<=n;i++){
54     for(int j=1;j<=n;j++) slack[j] = 1e9;
55     for(;;){
56         for(int j=1;j<=n;j++) inS[j] = inT[j] = 0;
57         if(match(i)) break;
58         update();
59     }
60     }
61     double ans = 0;
62     for(int i=1;i<=n;i++) ans += lx[i] + ly[i];
63     if(ans <0) return false;
64     else return true;
65 }
66 
67 double divide(double l,double r){
68     if(r-l <= eps) return l;
69     double mid = (l+r)/2.0;
70     int flag = KM(mid);
71     if(flag) return divide(mid,r);
72     else return divide(l,mid);
73 }
74 
75 int main(){
76     read();
77     printf("%.6lf",divide(0,1E4));
78     return 0;
79 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/9117690.html