hdu4619:http://acm.hdu.edu.cn/showproblem.php?pid=4619
题意:题目大意:给你两种纸牌 ,一种水平放置共有n张 ,一种竖直放置共有m张。水平放置的纸牌占据点(x, y)和(x + 1 , y) , 竖直放置的纸牌占据点(x , y) 和 (x , y + 1)。水平放置的牌之间不会重叠,竖直放置的牌之间也不会重叠,但是水平放置的牌和竖直放置的牌之间可能会重叠。让你拿走一些牌,使剩下的牌之间不会重叠并且数量最多,输出剩余的最大牌数。
题解:对于这一题,我的解法是,首先观察知道,相加的线段只会是横着的和竖着的交替进行,对于这样的相交来说,要删除的点就是要么啥删除全部的横着的要么删除竖着的,所以删除的总数就是总数的1/2.所以,对于相交的线段,把他们看成点,然后对形成的图,统计每个连通子图点的个数就可。这一题也可以用匹配来做,就相当于求最大独立集。
1 #pragma comment(linker,"/STACK:100000000,100000000")//阔栈的语句 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define pb push_back 6 using namespace std; 7 const int maxn = 4002; 8 const int maxm = 3000002; 9 struct EDGE{ 10 int next, to; 11 }edge[maxm*2]; 12 struct Point{ 13 int x; 14 int y; 15 }num1[maxn],num2[maxn]; 16 int n,m,cnt,counts,ans; 17 int head[maxn]; 18 bool vis[maxn]; 19 void init(){ 20 cnt=0; 21 memset(head,-1,sizeof(head)); 22 memset(vis,0,sizeof(vis)); 23 } 24 void add(int u,int v){ 25 edge[cnt].to=v; 26 edge[cnt].next=head[u]; 27 head[u]=cnt++; 28 } 29 void DFS(int u){ 30 if(vis[u])return; 31 counts++; 32 vis[u]=1; 33 for(int i=head[u];i!=-1;i=edge[i].next) 34 DFS(edge[i].to); 35 } 36 bool judge(int a,int b){ 37 if(num1[a].x==num2[b].x&&num1[a].y==num2[b].y)return true; 38 if(num1[a].x==num2[b].x&&num1[a].y==num2[b].y+1)return true; 39 if(num1[a].x+1==num2[b].x&&num1[a].y==num2[b].y)return true; 40 if(num1[a].x+1==num2[b].x&&num1[a].y==num2[b].y+1)return true; 41 return false; 42 } 43 int main(){ 44 while(~scanf("%d%d",&n,&m)&&n){ 45 init(); 46 for(int i=1;i<=n;i++){ 47 scanf("%d %d",&num1[i].x,&num1[i].y); 48 } 49 for(int i=1;i<=m;i++){ 50 scanf("%d%d",&num2[i].x,&num2[i].y); 51 } 52 for(int i=1;i<=n;i++){ 53 for(int j=1;j<=m;j++){ 54 if(judge(i,j)){ 55 add(i,j+n); 56 add(j+n,i); 57 } 58 } 59 } 60 ans=0; 61 for(int i=1;i<=n+m;i++){ 62 counts=0; 63 DFS(i); 64 ans+=(counts+1)/2; 65 } 66 printf("%d ",ans); 67 } 68 }