POJ3565-Ants-KM变形
题意:
给出n个蚂蚁和苹果的坐标,对每个蚂蚁和苹果进行匹配(之间连一条线段),要求:任意两条线段不相交,输出一种方案。
思路:
因为三角形的两边之和大于第三边,
所有他们连线的所有线段和最小的时候线段一定不会相交,
所以这道题目就变成了二分图最小权值匹配,把任意两点间权值即为他们的距离,跑一遍KM即可。
注意:
套KM模板的时候,必须从1开始记录,否则不出结果
出来任意一种方案即可,不一定要和样例输出一样
double类型不要弄错
double类型比较的时候最好用<eps,因为精度问题,直接判断等于0可能会出错。
AC代码:

1 #include<stdio.h>
2 #include<iostream>
3 #include<queue>
4 #include<cmath>
5 #include<string.h>
6 using namespace std;
7 #define inf 0x3f3f3f3f
8 typedef long long ll;
9 const int N=110;
10 #define inf 0x3f3f3f3f
11 #define eps 1e-9
12
13 //man x、woman y
14 int n,match[N];
15 double love[N][N],exy[N],exx[N],need[N];//***
16 bool booky[N],bookx[N];
17 struct node
18 {
19 int x,y;
20 } ant[N],apple[N];
21
22 bool dfs(int woman)
23 {
24 booky[woman]=1;
25 for(int i=1; i<=n; i++)//man
26 {
27 if(bookx[i])
28 continue;
29 double w=exy[woman]+exx[i]-love[woman][i];//***
30 if(fabs(w)<=eps )//***
31 // if(w==0)
32 {
33 bookx[i]=1;
34 if(match[i]==-1||dfs(match[i]))
35 {
36 match[i]=woman;
37 return 1;
38 }
39 }
40 else
41 need[i]=min(need[i],w);
42 }
43 return 0;
44 }
45
46 int KM()
47 {
48 for(int i=1; i<=n; i++)
49 {
50 exy[i]=inf*(-1.0);//***
51 for(int j=1; j<=n; j++)
52 exy[i]=max(exy[i],love[i][j]);
53 }
54 for(int i=1; i<=n; i++)
55 {
56 fill(need+1,need+n+1,inf);//***
57 while(1)
58 {
59 memset(bookx,0,sizeof bookx);
60 memset(booky,0,sizeof booky);//放在这里清空,清空和break不能掉头否则TLE
61 if(dfs(i))
62 break;
63 double minn=inf;//***
64 for(int j=1; j<=n; j++)
65 {
66 if(bookx[j]==0)
67 minn=min(minn,need[j]);
68 }
69 for(int j=1; j<=n; j++)
70 {
71 if(booky[j])
72 exy[j]-=minn;
73 if(bookx[j])
74 exx[j]+=minn;
75 else
76 need[j]-=minn;
77 }
78 }
79 }
80 // int sum=0;
81 // for(int i=0; i<n; i++)
82 // sum+=love[match[i]][i];
83 // return sum;
84 }
85
86 int main()
87 {
88 while(~scanf("%d",&n))
89 {
90 memset(match,-1,sizeof(match));
91 memset(exx,0,sizeof exx);
92 memset(exy,0,sizeof exy);
93 for(int i=1; i<=n; i++)
94 scanf("%d %d",&ant[i].x,&ant[i].y);
95 for(int i=1; i<=n; i++)
96 scanf("%d %d",&apple[i].x,&apple[i].y);
97 for(int i=1; i<=n; i++)
98 {
99 for(int j=1; j<=n; j++)
100
101 love[j][i]=(-1.0)*sqrt((ant[i].x-apple[j].x)*(ant[i].x-apple[j].x)+(ant[i].y-apple[j].y)*(ant[i].y-apple[j].y));
102 }
103 KM();
104 for(int i=1; i<=n; i++)
105 printf("%d\n",match[i]);
106 }
107 return 0;
108 }
分类:
图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」