hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
题目大意
有2n个城市,其中有n个富有的城市,n个贫穷的城市,其中富有的城市只在一种资源富有,且富有的城市之间富有的资源都不相同,贫穷的城市只有一种资源贫穷,且各不相同,现在给出一部分贫穷城市的需求,每个需求都是一个贫穷的向一个富有的城市要资源,且每个富有的城市都想向贫穷的城市输入自己富有的那部分资源,现在为了运输要建设多条路,但是路与路之间不允许有交叉,求满足贫穷城市的各种要求最多可以建设多少条路
简化版::上面n个点,下面n个点,然后在这2n个点之间随意连线,一个点只能被连一次,问最多有多少条线不交叉。
解题思路:
将贫穷的城市按从小到大的顺序排列,然后求富有的城市序号的最大上升子序列LIS解决即可
Sample Input
2
1 2
2 1
3
1 2
2 3
3 1
Sample Output
Case 1:
My king, at most 1 road can be built.
Case 2:
My king, at most 2 roads can be built.
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long long 7 using namespace std ; 8 9 int f[500010] ; 10 //int dp[500010] ; 11 int n ; 12 13 struct city 14 { 15 int p ; 16 int r ; 17 }a[500010]; 18 19 bool cmp(const city &x , const city &y) 20 { 21 return x.p < y.p ; 22 } 23 24 int bsearch(int size, const int &a) { 25 int l=0, r=size-1; 26 while( l <= r ){ 27 int mid = (l+r)/2; 28 if( a > f[mid-1] && a <= f[mid] ) return mid;// >&&<= 换为: >= && < 29 else if( a < f[mid] ) r = mid-1; 30 else l = mid+1; 31 } 32 } 33 34 int LIS() 35 { 36 int i, j, size = 1; 37 f[0] = a[0].r; 38 //dp[0] = 1; 39 for( i=1; i < n; ++i ) 40 { 41 if( a[i].r <= f[0] ) j = 0; // <= 换为: < 42 else if( a[i].r > f[size-1] ) j = size++;// > 换为: >= 43 else j = bsearch(size, a[i].r); 44 f[j] = a[i].r; 45 //dp[i] = j+1; 46 } 47 return size; 48 } 49 50 int main () 51 { 52 //freopen("in.txt","r",stdin) ; 53 int Case = 1 ; 54 while(scanf("%d" , &n) !=EOF) 55 { 56 printf("Case %d:\n" , Case) ; 57 Case++ ; 58 int i ; 59 for (i = 0 ; i < n ; i++) 60 { 61 scanf("%d %d" , &a[i].p , &a[i].r) ; 62 } 63 sort(a,a+n,cmp) ; 64 int ans = LIS() ; 65 if (ans == 1) 66 printf("My king, at most %d road can be built.\n" , ans) ; 67 else 68 printf("My king, at most %d roads can be built.\n" , ans) ; 69 printf("\n") ; 70 71 } 72 73 74 return 0 ; 75 }