建图很好想到,主要是后面判断这条匹配边是不是必须变。 只需要吧当前这个匹配拆开,并且在图中吧这条边去掉。对对于左边的点去找增光路,如果不能找到,说明就是匹配必须边。
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #include<set> #include<ctime> #include<stdlib.h> #include<iostream> using namespace std; bool G[30][30]; struct Point { int x,y; void read() { scanf("%d %d",&x,&y); } }; Point rect[30][2]; Point num[30]; bool vis[30]; int link[30]; bool match(int x,int n) { for(int i=1;i<=n;i++) { if(G[x][i] && !vis[i]) { vis[i]=1; if(link[i]==-1 || match(link[i],n)) { link[i]=x; return 1; } } } return 0; } int Hungury(int n) { int ans=0; memset(link,-1,sizeof link); for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); if(match(i,n)) ans++; } return ans; } int main() { int n,ca=0; while(cin>>n&&n ) { for(int i=1;i<=n;i++) { scanf("%d %d",&rect[i][0].x,&rect[i][1].x); scanf("%d %d",&rect[i][0].y,&rect[i][1].y); } for(int i=1;i<=n;i++) num[i].read(); memset(G,0,sizeof G); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(rect[i][0].x<num[j].x && num[j].x<rect[i][1].x &&rect[i][0].y<num[j].y && num[j].y<rect[i][1].y) G[j][i]=1; } } printf("Heap %d\n",++ca); bool fg=0; if(Hungury(n)==n) fg=1; bool ff=0; if(fg) { for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); int tmp=link[i]; G[link[i]][i]=0; link[i]=-1; if(match(tmp,n)) { G[tmp][i]=1; continue; } if(ff) printf(" "); ff=1; printf("(%c,%d)",i+'A'-1,tmp); link[i]=tmp; G[tmp][i]=1; } } if(!ff) printf("none"); puts("\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-06 22:20:25