题目大意:河的两岸有两个不同的国家,一边是穷国,一边是富国,穷国和富国的村庄的标号是固定的,穷国要变富需要和富国进行交流,需要建桥,并且建的桥不能够有交叉。问最多可以建多少座桥。
思路:建路时如下图所示
当一边的点已经固定了的时候,另外一边按照从小到大的序列与当前的边连接,得到最少的交叉。
题目给的第二组测试数据,如果按照图一则可以建2座桥,图二建一座桥
3
1 2
2 3
3 1
图一 图二
一开始用的是一般的最长上升子序列,结果超时。后来想到之前poj做过的3903 Stock Exchange(二分法),当时也是超时后来用的是二分法做的就过了。又敲了一遍代码还是没有过,提示的是超时。看了讨论区以后发现输出格式不对,存在一条以上的路时road为复数roads。以前从来没有遇到这样的输出,这次也算是一次积累吧!改了以后还是超时。上网百度了一下人家的做法,发现了一个新的技巧,因为每一个点只有一个所以不用排序,输入的u v可以直接用数组标记,line[u] = v;而我之前做的代码是先用sort函数将u排序后求解,时间变长。嗯,不错这又是一个好方法。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define MAX 500005
int point[MAX];
int num, stack[MAX], top;
int main()
{
int i, cnt, max, a, b;
int low, high, mid;
cnt = 0;
while (scanf("%d", &num)!=EOF)
{
cnt++;
max = 0;
for (i=0; i<num; i++)
{
scanf("%d%d", &a, &b);
point[a] = b;//不用排序
}
top = 0;
stack[0] = -1;
for (i=1; i<=num; i++)
{
if (top==0 || point[i]>stack[top])
{
top++;
stack[top] = point[i];
}
else
{
low = 0;
high = top;
while (low <= high)
{
mid = (high+low) / 2;
if (point[i] > stack[mid])
low = mid + 1;
else
high = mid - 1;
}
stack[low] = point[i];
}
}
if (top==1)
printf("Case %d:\nMy king, at most %d road can be built.\n\n", cnt, top);
else
printf("Case %d:\nMy king, at most %d roads can be built.\n\n", cnt, top);
}
return 0;
}
转载请注明出处:http://blog.csdn.net/u010499449