当前位置: 代码迷 >> 综合 >> POJ 1486 唯一二分图匹配 好题
  详细解决方案

POJ 1486 唯一二分图匹配 好题

热度:1   发布时间:2024-01-20 20:18:18.0

一道很好的题目。

大意:

很多透明的矩形薄片平摊在平面上,每个矩形薄片有数字编号。

现在给出矩形薄片的边界与编号的坐标。

求出能唯一确定的矩形薄片的字母标号与数字编号。

很容易转化成二分图的题。

开始题意弄错以为是必须全部都唯一匹配则输出匹配序,不行则输出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;
}