zoukankan      html  css  js  c++  java
  • 题解 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;
    } 
    
  • 相关阅读:
    Windows平台下Android应用抓包挖掘漏洞方法
    长城宽带核心系统存严重漏洞,数十万用户、账单信息存泄露风险
    互联网公司站点通病之弱口令
    【Python】python-一个class继承的小case
    【Python】Python-skier游戏[摘自.与孩子一起学编程]
    【Python】一个python实例:给重要的文件创建备份.摘自crossin-python简明教程
    【JMeter】JMeter完成一个java请求的压测
    【Tcpcopy】离线回放功能
    【JMeter】Jmeter-完成一个http压力测试
    Apache-AB压力测试实例
  • 原文地址:https://www.cnblogs.com/martian148/p/13917487.html
Copyright © 2011-2022 走看看