Ants POJ - 3565 二分图带权匹配 KM算法

题目链接

题目大意

有n个白点和n个黑点 每个白点要与黑点链接 要求所有线段都不相交

题目思路

若是两个线段相交 就可以让两个交点交换一下

如下图

变为下图

这样不会交叉并且由于三角线两边大于第三边可知 长度一定变小

因此原题让所有线段都不相交可以转化为让所有线段的和最小

接下来将题目转化为 二分图最大全匹配的模板 白点黑点分别作为左右图

每个点之间的距离 作为边权

接下来直接套KM板子就好

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll inf_ll = 1000000.0;
const int maxn=1e5+10;
const int N=200+10;
int n;
struct node{
	double x,y;
}e[N*N];
double  w[N][N];
ll mb[N+7],vb[N+7],p[N+7];
double ka[N+7],kb[N+7],c[N+7];

//ll qf,qb,q[N+7];
void Bfs(int u){//模板
    ll a,v=0,vl=0;
	double d;
    for(int i=1;i<=n;i++) p[i]=0,c[i]=1000000.0;
    mb[v]=u;
    do {
        a=mb[v],d=inf_ll,vb[v]=1;
        for(int b=1;b<=n;b++)if(!vb[b]){
            if(c[b]>ka[a]+kb[b]-w[a][b])
                c[b]=ka[a]+kb[b]-w[a][b],p[b]=v;
            if(c[b]<d) d=c[b],vl=b;
        }
        for(int b=0;b<=n;b++)
            if(vb[b]) ka[mb[b]]-=d,kb[b]+=d;
            else c[b]-=d;
        v=vl;
    } while(mb[v]);
    while(v) mb[v]=mb[p[v]],v=p[v];
}
ll KM(){
    for(int i=1;i<=n;i++) mb[i]=0,ka[i]=kb[i]=0.0;
    for(int a=1;a<=n;a++){
        for(int b=1;b<=n;b++) vb[b]=0;
        Bfs(a);
    }
    ll res=0;
    for(int b=1;b<=n;b++) res+=w[mb[b]][b];
    return res;
}
double dis(const node &x,const node &y){
    return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
int main()
{
	cin>>n;
	int a,b;
	for(int i=1;i<=n;i++)
	{
		cin>>e[i].x>>e[i].y;
	}
	for(int i=1;i<=n;i++)
	{
		cin>>e[i+n].x>>e[i+n].y;//白 
	}
	for(int i=1;i<=n;i++)//白 
	{
		for(int j=1;j<=n;j++)
		{
			//add(i,j,dis(e[i+n],e[j]));
			w[i][j]=dis(e[i+n],e[j]);
			w[i][j]*=-1.0;//求最小值别忘乘-1
		}
	}
	KM();
	for(int i=1;i<=n;i++)cout<<mb[i]<<endl;
	return 0;
}

还有一道带权匹配KM题

2021牛客第五场J-Jewels

原题链接

题解博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值