POJ 2253 Frogger
POJ 1797 Heavy Transportation
这两道题分别是求起点到终点的所有路径中路径内的最大边的最小值,以及所有路径中最小边的最大值
题目有点绕,但用Kruskal的思想来想就是:
将所有边排序,通过并查集把起点和终点连接起来的过程中,最后一条使起点和终点连接的边的权值就是答案
如下,以Frogger这道题为例
求的是起点到终点的所有路径中路径内的最大边的最小值
我们可以先把所有的边按照从小到大排序
遍历边集E,对每条边的端点u,v,通过并查集将他们表示相连
每次连完后判断起点和终点是否在同一集合里,如果在则输出这次的边权,即为答案
算法的合理性其实很清楚,贪心地从最短的边开始找起,一直到起点终点相连,最后加入的边是此次路径内的边的最大值,就是答案。
严谨的证明可以通过反证或者替代法。
下面仅用反证法证明正确性:
记上述算法最后的结果为v,假设有更小的v’满足题意。
则v’在边集E中的顺序一定在v的前面
而有v的定义知,遍历到v’时起点和终点并未相连,因此不满足题意。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
const int maxn = 205;
double x[maxn],y[maxn];
int father[maxn];
int findFather(int x)
{
return x==father[x]?x:father[x] = findFather(father[x]);
}
double getd(int i,int j)
{
double t = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
return sqrt(t);
}
void init()
{
for(int i=1;i