码迷,mamicode.com
首页 > 其他好文 > 详细

poj3565Ants【最小权匹配】

时间:2014-08-11 23:55:23      阅读:491      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   2014   

大意:

bubuko.com,布布扣左图为一个坐标轴上的点  其中黑点代表ants 白点代表apple 问怎样安排ants匹配apple才能使人一两条边不想交

分析:

 

bubuko.com,布布扣

如左图,我们假设a->d,b->c为一个最佳匹配  交点为e

那么ad+bc = ae+ ed + be + ec = (ae + ec) + (be + ed)  该值大于ac+bd

所以匹配为最佳匹配不成立

因此我们只要求出二分图的最小匹配就是结果了

但是wa了;

wa的代码:

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 const long long maxn = 105;
 7 const long long INF = 10000000000;
 8 
 9 
10 long long W[maxn][maxn];
11 long long Lx[maxn], Ly[maxn];
12 long long Left[maxn];
13 bool S[maxn], T[maxn];
14 
15 long long n;
16 
17 bool match(long long i) {
18     S[i] = true;
19     for(long long j = 1; j <= n; j++) if (Lx[i]+Ly[j] == W[i][j] && !T[j]){
20         T[j] = true;
21         if (!Left[j] || match(Left[j])){
22             Left[j] = i;
23             return true;
24         }
25     }
26     return false;
27 }
28 
29 void update() {
30     long long a = INF;
31     for(long long i = 1; i <= n; i++) if(S[i])
32         for(long long j = 1; j <= n; j++) if(!T[j])
33             a = min(a, Lx[i]+Ly[j] - W[i][j]);
34     for(long long i = 1; i <= n; i++) {
35         if(S[i]) Lx[i] -= a;
36         if(T[i]) Ly[i] += a;
37     }
38 }
39 
40 void KM() {
41     for(long long i = 1; i <= n; i++) {
42         Left[i] = Lx[i] = Ly[i] = 0;
43         for(long long j = 1; j <= n; j++)
44             Lx[i] = max(Lx[i], W[i][j]);
45     }
46     for(long long i = 1; i <= n; i++) {
47         for(;;) {
48             for(long long j = 1; j <= n; j++) S[j] = T[j] = false;
49             if(match(i)) break; else update();
50         }
51     }
52 }
53 
54 
55 struct Node {
56     long long x, y;
57 }ant[maxn], apple[maxn];
58 
59 
60 long long dist(Node n1, Node n2) {
61     return (n1.x - n2.x) * (n1.x - n2.x) + (n1.y - n2.y) * (n1.y - n2.y);
62 }
63 
64 int main() {
65     while(EOF != scanf("%lld",&n)) {
66         for(long long i = 1; i <= n; i++) scanf("%lld %lld",&ant[i].x, &ant[i].y);
67         for(long long i = 1; i <= n; i++) scanf("%lld %lld",&apple[i].x, &apple[i].y);
68         memset(W, 0, sizeof(W));
69         for(long long i = 1; i <= n; i++) {
70             for(long long j = 1; j <= n; j++) {
71                 W[i][j] = -dist(apple[i], ant[j]);
72             }
73         }
74         KM();
75         for(long long i = 1; i <= n; i++) {
76             printf("%lld\n",Left[i]);
77         }
78     }
79     return 0;
80 }
wa的代码

想了好长时间终于知道哪儿错了

我只是用的距离的平方做的比较

也就是说 a^2 + b ^ 2 > c ^ c + d ^ 2 不能推出 a + b > c + d

比如1^2 + 100^2 > 50 ^ 2 + 51 ^2 但是 1 + 100 < 51 + 52

所以平方比较是错的

ac代码如下:

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 const int maxn = 105;
 8 const double INF = 1000000000;
 9 
10 double W[maxn][maxn];
11 double Lx[maxn], Ly[maxn];
12 int Left[maxn];
13 bool S[maxn], T[maxn];
14 
15 int n;
16 
17 bool match(int i) {
18     S[i] = true;
19     for(int j = 1; j <= n; j++) if ( (abs(Lx[i]+Ly[j] - W[i][j]) < 0.00000001) && !T[j]){
20         T[j] = true;
21         if (!Left[j] || match(Left[j])){
22             Left[j] = i;
23             return true;
24         }
25     }
26     return false;
27 }
28 
29 void update() {
30     double a = INF;
31     for(int i = 1; i <= n; i++) if(S[i])
32         for(int j = 1; j <= n; j++) if(!T[j])
33             a = min(a, Lx[i]+Ly[j] - W[i][j]);
34     for(int i = 1; i <= n; i++) {
35         if(S[i]) Lx[i] -= a;
36         if(T[i]) Ly[i] += a;
37     }
38 }
39 
40 void KM() {
41     for(int i = 1; i <= n; i++) {
42         Left[i] = 0;
43         Lx[i] = Ly[i] = 0.0;
44         for(int j = 1; j <= n; j++)
45             Lx[i] = max(Lx[i], W[i][j]);
46     }
47     for(int i = 1; i <= n; i++) {
48         for(;;) {
49             for(int j = 1; j <= n; j++) S[j] = T[j] = false;
50             if(match(i)) break; else update();
51         }
52     }
53 }
54 
55 struct Node {
56     double x, y;
57 }ant[maxn], apple[maxn];
58 
59 double dist(Node n1, Node n2) {
60     return sqrt((n1.x - n2.x) * (n1.x - n2.x) + (n1.y - n2.y) * (n1.y - n2.y));
61 }
62 
63 int main() {
64     //freopen("3565.txt","r",stdin);
65     while(EOF != scanf("%d",&n)) {
66         for(int i = 1; i <= n; i++) scanf("%lf %lf",&ant[i].x, &ant[i].y);
67         for(int i = 1; i <= n; i++) scanf("%lf %lf",&apple[i].x, &apple[i].y);
68         memset(W, 0, sizeof(W));
69         for(int i = 1; i <= n; i++) {
70             for(int j = 1; j <= n; j++) {
71                 W[i][j] = -dist(apple[i], ant[j]);
72             }
73         }
74         KM();
75         for(int i = 1; i <= n; i++) {
76             printf("%d\n",Left[i]);
77         }
78     }
79     return 0;
80 }
ac代码

 

poj3565Ants【最小权匹配】,布布扣,bubuko.com

poj3565Ants【最小权匹配】

标签:style   blog   http   color   os   io   for   2014   

原文地址:http://www.cnblogs.com/zhanzhao/p/3905583.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!