UVALive 4043 Ants

题意:

  给n个黑点和n个白点的坐标,然后连n条线段连接黑点和白点,使得所有线段不相交,求匹配方案。

解法:

  白书上的例题,建图思路蛮好的。

  二分图,黑点和白点在两个集合里。然后求最小匹配,这样的结果肯定保证线段不相交。为什么呢?

  因为不存在三点共线,所以对于两条线段来说,如果他们相交了,我们可以交换一下匹配的点使得四个点构成两条不相交的线,这样结果肯定要变小,画个图就知道了。

p.s.貌似卡精度??被卡爆了。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #define N 110
 7 using namespace std;
 8 typedef long long ll;
 9 const double inf=1e40;
10 const double eps=1e-6;
11 double s[N][N],slack[N];
12 double lx[N],ly[N];
13 int mat[N],n;
14 bool vx[N],vy[N];
15 bool dfs(int u){
16     vx[u]=1;
17     for(int i=1;i<=n;i++){
18         if(!vy[i]){
19             double t=lx[u]+ly[i]-s[u][i];
20             if(fabs(t)<eps){
21                 vy[i]=1;
22                 if(mat[i]==-1||dfs(mat[i])){
23                     mat[i]=u;
24                     return 1;
25                 }
26             }else slack[i]=min(slack[i],t);
27         }
28     }
29     return 0;
30 }
31 void KM(){
32     memset(mat,-1,sizeof(mat));
33     memset(ly,0,sizeof(ly));
34     for(int i=1;i<=n;i++){
35         lx[i]=-inf;
36         for(int j=1;j<=n;j++)
37             lx[i]=max(lx[i],s[i][j]);
38     }
39     for(int i=1;i<=n;i++){
40         for(int j=1;j<=n;j++)slack[j]=inf;
41         while(1){
42             memset(vx,0,sizeof(vx));
43             memset(vy,0,sizeof(vy));
44             if(dfs(i))break;
45             double d=inf;
46             for(int j=1;j<=n;j++)
47                 if(!vy[j])d=min(d,slack[j]);
48             for(int j=1;j<=n;j++)
49                 if(vx[j])lx[j]-=d;
50             for(int j=1;j<=n;j++)
51                 if(vy[j])ly[j]+=d;
52         }
53     }
54     for(int i=1;i<=n;i++)
55         printf("%d\n",mat[i]);
56 }
57 double bx[N],by[N],wx[N],wy[N];
58 double dis(int i,int j){
59     return sqrt((wx[i]-bx[j])*(wx[i]-bx[j])+(wy[i]-by[j])*(wy[i]-by[j]));
60 }
61 int main(){
62     int flag=0;
63     while(cin>>n){
64         for(int i=1;i<=n;i++)cin>>bx[i]>>by[i];
65         for(int i=1;i<=n;i++)cin>>wx[i]>>wy[i];
66         for(int i=1;i<=n;i++)
67             for(int j=1;j<=n;j++)
68                 s[i][j]=-dis(i,j);
69         if(flag)printf("\n");
70         KM();
71         flag=1;
72     }
73     return 0;
74 }

 

posted @ 2013-02-23 22:51  silver__bullet  阅读(485)  评论(0编辑  收藏  举报