【20171111】 Codevs 1214 线段覆盖
题目描述 Description给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。
输入描述 Input Description输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。
输出描述 Output Description输出第一行是一个整数表示最多剩下的线段数。
样例输入 Sample Input3
6 3
1 3
2 5
样例输出 Sample Output2
数据范围及提示 Data Size & Hint0<N<100
我想,如果把覆盖关系转化为“边”的话,那么输入数据可以转化为一个图,
题目就变为:删掉最少的点,使得图中剩余点两两不能连通。
好简单呀,就按照每个点的度降序删点即可!
但是我的代码速度有待提高……
数组存图,n^2,
1 //begin at 16:40 2 #include<stdio.h> 3 #include<stdlib.h> 4 #define maxn 101 5 #define _Cover !(ival[i][0]>=ival[j][1]||ival[i][1]<=ival[j][0]) 6 int ival[maxn][3];//interval 7 //ival[i][2] is the amount of 'i' Coverd intervals 8 int g[maxn][maxn];//regard the cover 9 int countCover=0; 10 int n; 11 int searchMaxCover() 12 { 13 int ans=0,i,maxi; 14 for(i=0;i<n;i++) 15 { 16 if(ival[i][2]>ans) 17 { 18 maxi=i; 19 ans=ival[i][2]; 20 } 21 } 22 return maxi; 23 } 24 int main() 25 { 26 scanf("%d",&n); 27 int i,j,t; 28 for(i=0;i<n;i++) 29 { 30 scanf("%d%d",&ival[i][0],&ival[i][1]); 31 if(ival[i][0]>ival[i][1]) 32 { 33 t=ival[i][0];ival[i][0]=ival[i][1];ival[i][1]=t; 34 } 35 ival[i][2]=0;//the amount of Coverd intervals 36 for(j=0;j<i;j++) 37 { 38 if(_Cover) 39 { 40 g[i][j]=g[j][i]=1;//create the edges 41 ival[i][2]++; 42 ival[j][2]++; 43 countCover++; 44 } 45 else 46 g[i][j]=g[j][i]=0; 47 } 48 } 49 if(countCover==0) 50 { 51 printf("%d\n",n-1-i); 52 return 0; 53 } 54 int p,q; 55 i=0; 56 while(countCover>0) 57 { 58 i++; 59 p=searchMaxCover(); 60 for(j=0;j<n;j++) 61 { 62 if(g[p][j]==1) 63 { 64 g[p][j]=g[j][p]=0;//delete the edge 65 ival[p][2]--; 66 ival[j][2]--; 67 countCover--; 68 } 69 } 70 if(countCover==0) 71 { 72 printf("%d\n",n-i); 73 return 0; 74 } 75 } 76 return 0; 77 } 78 //end at 17:50