题目链接:https://vjudge.net/problem/UVALive-4043

题意:

给出n个白点和n个黑点的坐标, 要求用n条不相交的线段把他们连接起来,其中每条线段恰好连接一个白点和黑点,每个点恰好连接到一条线段。输出每个白点与其相连的黑点的编号。

题解:

1.首先随便配对。然后,如果存在两对黑白点的线段是相交的,那么就交换他们的配对对象。交换之后重新形成的线段就不会相交了(画画图就可看出)。而且可以推出一个结论:交换之后,两条线段之和必定变小。这是因为根据三角形定理:

2.有了上述结论之后,我们就能推出:对于当前配对,如果线段总和还能继续变小,那么就可能存在交叉;但如果线段总和不能再小了,即已经达到最小,那么就不存在交叉了。所以我们只需要求最大权匹配(边权取反),就能满足要求了。

代码如下:

 #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const double EPS = 1e-;
const int MOD = 1e9+;
const int MAXN = 1e2+; struct Node{
double x, y;
}black[MAXN], white[MAXN]; int nx, ny;
double g[MAXN][MAXN];
int linker[MAXN];
double lx[MAXN], ly[MAXN], slack[MAXN];
bool visx[MAXN], visy[MAXN]; bool DFS(int x)
{
visx[x] = true;
for(int y = ; y<=ny; y++)
{
if(visy[y]) continue;
double tmp = lx[x] + ly[y] - g[x][y];
if(tmp<EPS)
{
visy[y] = true;
if(linker[y]==- || DFS(linker[y]))
{
linker[y] = x;
return true;
}
}
else
slack[y] = min(slack[y], tmp);
}
return false;
} void KM()
{
memset(linker, -, sizeof(linker));
memset(ly, , sizeof(ly));
for(int i = ; i<=nx; i++)
{
lx[i] = -INF;
for(int j = ; j<=ny; j++)
lx[i] = max(lx[i], g[i][j]);
} for(int x = ; x<=nx; x++)
{
for(int i = ; i<=ny; i++)
slack[i] = INF;
while(true)
{
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy)); if(DFS(x)) break;
double d = INF;
for(int i = ; i<=ny; i++)
if(!visy[i])
d = min(d, slack[i]); for(int i = ; i<=nx; i++)
if(visx[i])
lx[i] -= d;
for(int i = ; i<=ny; i++)
{
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
}
} int main()
{
int kase = , n;
while(scanf("%d", &n) != EOF)
{
if(kase++) printf("\n"); nx = ny = n;
for (int i = ; i <= n; i++)
scanf("%lf%lf", &black[i].x, &black[i].y);
for (int i = ; i <= n; i++)
scanf("%lf%lf", &white[i].x, &white[i].y); for (int i = ; i <= n; i++)
{
double x1 = white[i].x, y1 = white[i].y;
for (int j = ; j <= n; j++)
{
double x2 = black[j].x, y2 = black[j].y;
g[i][j] = -sqrt( (x1-x2)*(x1 - x2) + (y1-y2)*(y1-y2) );
}
} KM();
for(int i = ; i<=n; i++)
printf("%d\n", linker[i]);
}
}

最新文章

  1. C和指针 第九章 习题
  2. JVM执行引擎总结(读《深入理解JVM》) 早期编译优化 DCE for java
  3. mORMot使用基础
  4. Codeforces Round #206 (Div. 2) A. Vasya and Digital Root
  5. (转载)OC学习篇之---归档和解挡
  6. KeilC51高级编程
  7. AMS1117典型电路
  8. HTML5 3D翻书效果(双面效应)
  9. Codeforces Round #375 (Div. 2)A. The New Year: Mee
  10. K:Union-Find(并查集)算法
  11. selenium-java web自动化测试工具
  12. docker之NGINX镜像构建
  13. 解决linux中使用git,ssh每次都要输入密码
  14. .NET分布式缓存Redis从入门到实战
  15. golang:mime.Decode、mime.DecodeHeader
  16. 函数使用十一:FTP
  17. 摆脱定时任务的cron表达式的困扰
  18. ES6箭头函数this指向
  19. db2错误代码大全
  20. DOM对象操作html元素1

热门文章

  1. sql使用row_number()查询标记行号
  2. Java学习关于集合框架的基础接口--Collection接口
  3. angularjs自己总结
  4. 使用JQuery.slideBox实现图片滚动效果
  5. Java日志实战及解析 - 引导
  6. centos配置mutt跟msmtp发送邮件
  7. Codevs 1497 取余运算== 洛谷P 1226
  8. 免费SSL申请
  9. Entity framework自定义字段实现思路
  10. Maven使用tomcat7-maven-plugin插件run时出现错误: A child container failed during start java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component