hdu 1025 Constructing Roads In JGShining's Kingdom(二分法+最长上升子序列)

     题目大意:河的两岸有两个不同的国家,一边是穷国,一边是富国,穷国和富国的村庄的标号是固定的,穷国要变富需要和富国进行交流,需要建桥,并且建的桥不能够有交叉。问最多可以建多少座桥。

     思路:建路时如下图所示

                当一边的点已经固定了的时候,另外一边按照从小到大的序列与当前的边连接,得到最少的交叉。

          题目给的第二组测试数据,如果按照图一则可以建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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值