题意

给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案。

思路

一开始没想到怎么用最小权匹配……后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)……还是too young too simple……没有融会贯通……

代码

[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; i ++)
using namespace std;
const int MAXV = 205; //X or Y点集大小
const int oo = 0x3fffffff;

const double eps = 1e-8;
template <class weight_type>
struct MaximalMatchingOfWeightedBipartiteGraph{
weight_type w[MAXV][MAXV]; //权值
int sv, tv; //Perfect Matching, sv should equal to tv
bool S[MAXV], T[MAXV];
weight_type lx[MAXV], ly[MAXV]; //X、Y点集可行顶标
int left[MAXV];
weight_type slack[MAXV];
void init(int v){
sv = tv = v;
MEM(w, 0);
}
void add_uedge(int u, int v, weight_type _w){
w[u][v] = _w;
}
bool cross_path(int u){
S[u] = true;
for (int v = 1; v <= tv; v ++){
if(T[v]) continue;
weight_type t = lx[u] + ly[v] - w[u][v];
if (t < eps){
T[v] = true;
if (left[v] == 0 || cross_path(left[v])){
left[v] = u;
return true;
}
}
else{
slack[v] = min(slack[v], t);
}
}
return false;
}
weight_type solve(){
//Init
MEM(left, 0);
for (int i = 1; i <= sv; i ++){
lx[i] = 0;
ly[i] = 0;
for (int j = 1; j <= tv; j ++)
lx[i] = max(lx[i], w[i][j]);
}
//Main
for (int i = 1; i <= sv; i ++){
for (int j = 1; j <= tv; j ++) slack[j] = oo;
while(1){
MEM(S, false); MEM(T, false);
if (cross_path(i)){
break;
}
else{
weight_type d = oo;
for (int j = 1; j <= tv; j ++)
if (!T[j]) d = min(d, slack[j]);
for (int j = 1; j <= sv; j ++)
if (S[j]) lx[j] -= d;
for (int j = 1; j <= tv; j ++){
if (T[j]) ly[j] += d;
else slack[j] -= d;
//匈牙利树中T集点ly不变,S集点lx减小,更新slack值
}
}
}
}
weight_type res = 0;
for(int i = 1; i <= sv; i ++) res += lx[i];
for(int i = 1; i <= tv; i ++) res += ly[i];
return res;
}
};
MaximalMatchingOfWeightedBipartiteGraph <double> km;

struct Point{
double x, y;
}p[MAXV];
double dist(int i, int j){
return sqrt((p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y)*(p[i].y - p[j].y));
}

int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n;
while(scanf("%d", &n) != EOF){
REP(i, 1, n){
scanf("%lf %lf", &p[i+n].x, &p[i+n].y);
}
REP(i, 1, n){
scanf("%lf %lf", &p[i].x, &p[i].y);
}
km.init(n);
REP(i, 1, n){
REP(j, 1, n){
km.add_uedge(i, j, -dist(i, j+n));
}
}
//printf("%f\n", -km.solve());
km.solve();
REP(i, 1, n){
printf("%d\n", km.left[i]);
}
}
return 0;
}
[/cpp]

POJ 3565 Ants (最小权匹配)的更多相关文章

  1. Poj(3686),最小权匹配,多重匹配,KM

    题目链接 The Windy's | Time Limit: 5000MS | Memory Limit: 65536K | | Total Submissions: 4939 | Accepted: ...

  2. POJ 3565 Ants 【最小权值匹配应用】

    传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: ...

  3. poj 2516(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=2516 思路:考虑某种货物,由于某个订货商可能接受来自不同地区的货物,而某一地区的货物也可能送给不同的订货商,显然不能直接进行匹配,必须 ...

  4. poj 3686(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=3686 思路:显然工件为X集,机器为Y集合.由于每个机器一次只能加工一个部件,因此我们可以将一台机器拆成N个点,至于部件与机器之间连多大 ...

  5. poj 2195(KM求最小权匹配)

    题目链接:http://poj.org/problem?id=2195 思路:我们都知道KM使用来求最大权匹配的,但如果要求最小权匹配,只需把图中的权值改为负值,求一次KM,然后权值和取反即可. ht ...

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

    [POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS   Memory Limit ...

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

    [POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  8. POJ 2400 最小权匹配

    吐槽:首先,这道题的输入居然是错的.要将上下两个矩阵的位置换一下才可以出样例,也就是上面那个矩阵是employee对Supervisor的打分,下面那个矩阵才是Supervisor对employee的 ...

  9. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

随机推荐

  1. 提权后获取linux root密码

    提权后获取linux root密码 2011-09-09 10:45:25     我来说两句      收藏    我要投稿 在webbackdoor本身是root(可能性小的可怜)或通过某漏洞溢出 ...

  2. HDU 4825 Xor Sum(二进制的字典树,数组模拟)

    题目 //居然可以用字典树...//用cin,cout等输入输出会超时 //这是从别处复制来的 #include<cstdio> #include<algorithm> #in ...

  3. (转)排列算法 Permutation Generation

    转自:http://www.cnblogs.com/dragonpig/archive/2010/01/21/1653680.html http://www.notesandreviews.com/p ...

  4. UVA 562 Dividing coins

    题目描述:给出一些不同面值的硬币,每个硬币只有一个.将这些硬币分成两堆,并且两堆硬币的面值和尽可能接近. 分析:将所有能够取到的面值数标记出来,然后选择最接近sum/2的两个面值 状态表示:d[j]表 ...

  5. 自己的gitignore文件

    *.bak*.txt*.vm.gitignore#svn.svn/# built application files*.apk*.ap_ # files for the dex VM*.dex # J ...

  6. Android 基于Socket的聊天应用(二)

    很久没写BLOG了,之前在写Android聊天室的时候答应过要写一个客户(好友)之间的聊天demo,Android 基于Socket的聊天室已经实现了通过Socket广播形式的通信功能. 以下是我写的 ...

  7. NVDIMM典型应用及技术发展

    1.典型应用之全系统保护 全系统保护采用超级内存作为系统主存.在系统异常掉电时,将整个系统的运行状态(包括CPU,芯片组,其他外设以及所有进程的信息)存入超级内存.在供电恢复后,利用超级内存中的数据, ...

  8. JMS基本概念

    原文:http://blog.csdn.net/jiuqiyuliang/article/details/46701559 The Java Message Service (JMS) API is ...

  9. CentOS进程资源占用高原因分析命令

    1.查看进程的线程:ps -eLf|egrep 'gateserver|UID' 2.跟踪线程调用: strace  -p 15530 3.统计线程中函数的调用小号CPU时间:strace  -p 1 ...

  10. iOS:VFL语言

    VFL语言   介绍: 什么是VFL语言? VFL全称是Visual Format Language,翻译过来是“可视化格式语言” VFL是苹果公司为了简化Autolayout的编码而推出的抽象语言 ...