poj3565Ants【最小权匹配】

大意:

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

分析:

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

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

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

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

但是wa了;

wa的代码:

 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代码如下:

 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

时间: 2024-09-30 19:50:04

poj3565Ants【最小权匹配】的相关文章

POJ 3686 The Windy&#39;s【最小权匹配(神建图啊)】

大意:有n个任务m个机器,告诉你n*m的矩阵表示每个任务在每个机器上完成需要的时间 问所有任务完成的总时间最少?(比如第一个任务在第一分钟完成第二个任务在第二分钟完成   则总时间为1 + 2 = 3 分析: 该题自己做的时候没有思路 后来在网上搜题解,感觉建图真是太厉害了 假设最优情况下,个个任务需要的时间分别为a1, a2, a3, ……,an 那么总时间t = n * a1 + (n - 1) * a2 + ……+ 2 * an - 1 + an 也就是说只需要考虑系数就可以了 我们先假设

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

ural 1076 KM求最小权匹配

贴模板~ KM算法引进了顶标函数,不断缩小这个顶标来让相等子图的可能范围扩大 #include<iostream> #include<cstring> //KM 复杂度O^3 using namespace std; const int N=200; int lx[N],ly[N];//顶标函数 int w[N][N];//图 bool vix[N],viy[N]; int linky[N];// int lack;//每次顶标函数扩大的增量 int n,m; bool find(

二分图最佳匹配,求最大权匹配或最小权匹配

Beloved Sons http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1338 题意:国王有N个儿子,现在每个儿子结婚都能够获得一定的喜悦值,王子编号为1-N,有N个女孩的编号同样为1-N,每个王子心中都有心仪的女孩,现在问如果安排,能够使得题中给定的式子和最大. 分析:其实题目中那个开根号是个烟雾弹,只要关心喜悦值的平方即可.那么对王子和女孩之间构边,边权为喜悦值的平方,对于每一个王子虚拟出一个女孩边权为0,这样是为了所

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

[POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2538   Accepted: 719 Description Suppose some supervisors each get to hire a new person for their department. There are N

[ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receivesN orders for toys. The man

【POJ 2195】 Going Home(KM算法求最小权匹配)

[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20303   Accepted: 10297 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit ste

poj2195 bfs+最小权匹配

题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题. 这题就是建图有点麻烦,但绝不抽象,直接用BFS遍历每个人到所有房子的距离,遍历出一个就拉一条人到房子有向边,建完图就是套模板了. 注意:KM算法是求最大权匹配的,要求最小权就要把所有边取相反数,最后结果再取相反数,但这只能是完美匹配,不完美匹配还要变一些. 1 #include<cstdio> 2 #include