一道很好的题目。
大意:
很多透明的矩形薄片平摊在平面上,每个矩形薄片有数字编号。
现在给出矩形薄片的边界与编号的坐标。
求出能唯一确定的矩形薄片的字母标号与数字编号。
很容易转化成二分图的题。
开始题意弄错以为是必须全部都唯一匹配则输出匹配序,不行则输出none.
现在的题意是求关键边... 不用删边,特判就好.
#include<iostream> #include<cstdio> using namespace std; struct RECT { int minx,maxx,miny,maxy; }rect[333]; struct POINT { int x,y; }point[333]; struct EDGE { int v,next; }E[333333]; int Edgenum,ptr[333],match[333],match2[333]; bool vis[333]; bool judge( RECT a, POINT b ) { if( a.minx<b.x && b.x<a.maxx && a.miny<b.y && b.y<a.maxy ) return true; return false; } void addEdge( int u,int v ) { E[Edgenum].v=v; E[Edgenum].next=ptr[u]; ptr[u]=Edgenum++; } bool Match( int cur,int *array,int xu=0,int xv=0 ) { for( int i=ptr[cur];i!=-1;i=E[i].next ) { if( xu==cur && xv==E[i].v ) continue; if( !vis[E[i].v] ) { vis[E[i].v]=true; if( array[E[i].v]==-1 || Match(array[E[i].v],array,xu,xv) ) { array[E[i].v]=cur; return true; } } } return false; } int main() { int N;int cases=0; while( scanf("%d",&N)!=EOF,N ) { memset( match,-1,sizeof(match) ); memset( ptr,-1,sizeof(ptr) ); Edgenum=0; for( int i=1;i<=N;i++ ) scanf( "%d %d %d %d",&rect[i].minx,&rect[i].maxx,&rect[i].miny,&rect[i].maxy ); for( int i=1;i<=N;i++ ) scanf( "%d %d",&point[i].x,&point[i].y ); for( int i=1;i<=N;i++ ) for( int j=1;j<=N;j++ ) if( judge(rect[i],point[j]) ) addEdge(j+N,i);//用数字连方块 match为方块找数字 int MaxMatch=0; for( int i=N+1;i<=N+N;i++ ) { memset( vis,0,sizeof(vis) ); if( Match(i,match) ) MaxMatch++; } printf( "Heap %d\n",++cases ); if( MaxMatch!=N ) { printf( "none\n\n" ); continue; } bool blank=false; //枚举 断边 for( int i=1;i<=N;i++ ) { int NowMatch=0; memset( match2,-1,sizeof(match2) ); for( int j=N+1;j<=N+N;j++ ) { memset( vis,0,sizeof(vis) ); if( Match( j,match2,match[i],i ) ) NowMatch++; } if( NowMatch<MaxMatch ) { if( blank ) printf( " " ); blank=true; printf( "(%c,%d)",i+'A'-1,match[i]-N ); //printf( "none\n\n" ); //goto A; } } if( blank==false ) printf( "none" ); printf( "\n\n" ); } return 0; }