• 题解 UVA1411 【Ants】


    Link

    UVA1411 Ants

    Solve

    题目要求所有线段都不相交,等价于让每条线段的长度之和最小。

    如果第(i_1)个白点连第(j_1)个黑点,第(i_2)个白点连接第(j_2)个黑点,并且线段((i_1,j_1))((i_2,j_2))相交,那么交换一下,让(i_1)(j_2),让(j_1)(i_2),这样就不会交叉,并且有三角形两边和大于第三边可知,两条线段的长度和一定变小。

    所以就可以把(N)个白点看作左部点,(N)个端点看作右部端点,让第(i)个白点和第(j)个黑点连边,边权(w(i,j))就是他们在平面上的距离

    (KM)算法求二分图带权最小匹配时,我们把所有边权(w(i,j))取为相反数,然后转化为求二分图带权最大匹配,最后把答案(-ans)作为答案即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=105,INF=1<<30;
    int N,match[maxn];
    bool va[maxn],vb[maxn];
    double X_w[maxn],la[maxn],lb[maxn],Y_w[maxn],X_b[maxn],Y_b[maxn],w[maxn][maxn],delta,upd[maxn],ans;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    bool DFS(int x){
    	va[x]=1;
    	for(int y=1;y<=N;y++)
    		if(!vb[y]){
    			if(abs(la[x]+lb[y]-w[x][y])<1e-7){
    				vb[y]=1;
    				if(!match[y]||DFS(match[y])){
    					match[y]=x;
    					return true;
    				}
    			}
    			else upd[y]=min(upd[y],la[x]+lb[y]-w[x][y]); 
    		}
    	return false;
    }
    
    void KM(){
    	memset(match,0,sizeof match);
    	for(int i=1;i<=N;i++){
    		la[i]=-INF;
    		lb[i]=0;
    		for(int j=1;j<=N;j++)la[i]=max(la[i],w[i][j]);
    	}
    	for(int i=1;i<=N;i++)
    		while(true){
    			memset(va,0,sizeof va);
    			memset(vb,0,sizeof vb);
    			for(int j=1;j<=N;j++)upd[j]=INF;
    			if(DFS(i))break;delta=INF;
    			for(int j=1;j<=N;j++)
    				if(!vb[j])delta=min(delta,upd[j]);
    			for(int j=1;j<=N;j++){
    				if(va[j]) la[j]-=delta;
    				if(vb[j]) lb[j]+=delta;
    			}
    		}
    }
    int main(){
    	freopen("UVA1411.in","r",stdin);
    	freopen("UVA1411.out","w",stdout);
    	while(scanf("%d",&N)!=EOF){
    		for(int i=1;i<=N;i++)
    			scanf("%lf%lf",&X_w[i],&Y_w[i]);
    		for(int i=1;i<=N;i++)
    			scanf("%lf%lf",&X_b[i],&Y_b[i]);
    		for(int i=1;i<=N;i++)
    		for(int j=1;j<=N;j++)
    			w[j][i]=-sqrt((X_w[i]-X_b[j])*(X_w[i]-X_b[j])+(Y_w[i]-Y_b[j])*(Y_w[i]-Y_b[j]));
    		KM();
    		for(int i=1;i<=N;i++)printf("%d
    ",match[i]);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Inno Setup命令行安装卸载参数
    Fragment生命周期
    ubuntu 64位系统下加速Android模拟器
    Java中对SQLite数据库操作 操作db文件
    系统权限管理设计
    java 中的序列化是什么意思?有什么好处?
    js实现定时调用的函数setInterval()
    tomcat 并发配置优化
    centOS下 JDK的三种安装方式
    Linux 配置静态Ip地址
  • 原文地址:https://www.cnblogs.com/martian148/p/13917487.html
Copyright © 2020-2023  润新知