zoukankan      html  css  js  c++  java
  • 【题解】Luogu UVA1411 Ants

    原题传送门

    博客里对二分图匹配的详细介绍

    这道题是带权二分图匹配

    用的是KM算法

    我们要知道一个定理:要使线段没有相交,要使距离总和最小

    我们先把任意一对白点、黑点的距离算一下

    然后运用KM算法

    因为要最小权值,所以需要把权值取反来求最大。

    #include <bits/stdc++.h>
    #define N 105
    using namespace std;
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[25];int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline double Max(register double x,register double y)
    {
    	return x>y?x:y;
    }
    inline double Min(register double x,register double y)
    {
    	return x<y?x:y;
    }
    int n;
    double X1[N],Y1[N],X2[N],Y2[N];
    double dis[N][N];
    double lx[N],ly[N];
    int link[N],s[N],t[N];
    inline bool dfs(register int x)
    {
    	s[x]=1;
    	for(register int i=1;i<=n;++i)
    		if(fabs(lx[x]+ly[i]-dis[x][i])<1e-9&&!t[i])
    		{
    			t[i]=1;
    			if(!link[i]||dfs(link[i]))
    			{
    				link[i]=x;
    				return true;
    			}
    		}
    	return false;
    }
    inline void update()
    {
    	double a=23333333;
    	for(register int i=1;i<=n;++i)
    		if(s[i])
    			for(register int j=1;j<=n;++j)
    				if(!t[j])
    					a=Min(a,lx[i]+ly[j]-dis[i][j]);
    	for(register int i=1;i<=n;++i)
    	{
    		if(s[i])
    			lx[i]-=a;
    		if(t[i])
    			ly[i]+=a;
    	}
    }
    inline void KM()
    {
    	for(register int i=1;i<=n;++i)
    	{
    		link[i]=lx[i]=ly[i]=0;
    		for(register int j=1;j<=n;++j)
    			lx[i]=Max(lx[i],dis[i][j]);
    	}
    	for(register int i=1;i<=n;++i)
    		while(19260817)
    		{
    			for(register int j=1;j<=n;++j)
    				s[j]=t[j]=0;
    			if(dfs(i))
    				break;
    			else
    				update();
    		}
    }
    inline double getdis(register int x,register int y)
    {
    	return sqrt(pow(X1[x]-X2[y],2)+pow(Y1[x]-Y2[y],2));
    }
    int main()
    {
    	while(scanf("%d",&n)!=EOF)
    	{
    		for(register int i=1;i<=n;++i)
    			scanf("%lf %lf",&X1[i],&Y1[i]);
    		for(register int i=1;i<=n;++i)
    			scanf("%lf %lf",&X2[i],&Y2[i]);
    		for(register int i=1;i<=n;++i)
    			for(register int j=1;j<=n;++j)
    				dis[j][i]=-getdis(i,j);
    		KM();
    		for(register int i=1;i<=n;++i)
    			write(link[i]),puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    [程序员代码面试指南]数组和矩阵问题-未排序正数数组中累加和为给定值的最长子数组长度
    [Mysql]知识点
    [SSM项目]一-Eclipse 搭建marven-web项目 hello world!
    [BZOJ2252]矩阵距离(BFS)
    [Spring实战笔记]4面向切面编程的Spring-代理
    [程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)
    [Java]刷题中的Java基础
    MySql的大小写问题
    MySql密码丢失
    MySql的rpm安装
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10087461.html
Copyright © 2011-2022 走看看