POJ 1486二分图的必要边
题意:有n个大小不等透明的幻灯片(只有轮廓和上面的数字可见)A、B、C、D、E…按顺序叠放在一起,现在知道每个幻灯片大小,由于幻灯片是透明的,所以能看到幻灯片上的数字(给出了每个数字的坐标,但不知道这些数字分别属于哪个幻灯片),现在要你根据当前的已知信息,输出能够确定的幻灯片 编号和数字的匹配。
英语太差。一直坑在这句话 = =
将点和图进行匹配,求出最大匹配,再进行删边匹配,若匹配数不再为n,则说明这条边为必要边,输出。
input
4 6 22 10 20 4 18 6 16 8 20 2 18 10 24 4 8 9 15 19 17 11 7 21 11 2 0 2 0 2 0 2 0 2 1 1 1 1 0
output
Heap 1 (A,4) (B,1) (C,2) (D,3) Heap 2 none
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; bool used[1010]; int p[1010]; bool MAP[1010][1010]; int q[1010]; int X[1010][2]; int Y[1010][2]; int flag; int num,n,m; bool work(int c) { for(int i = 1; i <= n; i++) { if(!used[i] && MAP[c][i]) { used[i] = true; if(p[i]==-1 || work(p[i])) { p[i] = c; return true; } } } return false; } void sol() { num=0; memset(p,-1,sizeof(p)); for(int i = 1; i <= n; i++) { memset(used,0,sizeof(used)); if(work(i)) num++; } } int main() { int cas = 1; while(~scanf("%d",&n) && n) { memset(MAP,false,sizeof(MAP)); for(int i = 1; i <= n; i++) scanf("%d%d%d%d",&X[i][0],&X[i][1],&Y[i][0],&Y[i][1]); int a,b; for(int i = 1; i <= n; i++) { scanf("%d%d",&a,&b); for(int j = 1; j <= n; j++) { if(a > X[j][0] && a < X[j][1] && b > Y[j][0] && b< Y[j][1]) MAP[i][j] = true; } } sol(); printf("Heap %d\n", cas++); flag = 0; if(num == n) { for(int i = 1; i <= n; i++) q[i] = p[i]; for(int i = 1; i <= n; i++) { MAP[q[i]][i] = false; //删边 sol(); if(num == n) //判断是非为必要边 { continue; } else { if(flag) printf(" "); printf("(%c,%d)",'A'-1+i,q[i]); flag = 1; } MAP[q[i]][i] = true; //还原 } } if(!flag) printf("none"); printf("\n\n"); } return 0; }