(2-Point Matching of graph theory algorithms) hdu 1281 (board game)
A: give an n * m board and put it on the board. The cars that are placed on the Board cannot attack each other (they can attack each other on the same line or column), and only some dots can hold the board. Ask how many cars can be put at most, and how many grids must be put at most.
This is a good question for understanding Hungary algorithms. First, we need to find the maximum number of vehicles. This is a row-and-column matching problem. Suppose we use n left vertices to represent rows, and m right vertices are placed on the right. If a grid (x, y) can be placed in a car, connect x on the left and y on the right to create an edge. This is a classic model, so you don't have to worry much about it. Use the Hungary algorithm to obtain the maximum matching value at a time.
This is a good question. First, let me talk about the most violent method. Record the matching edge in the maximum match, and then remove this edge from the source image to check whether the maximum match is equal to the original one. The complexity of one request in Hungary is O (n * m ^ 2 ).
A total of n Hungary times. The total complexity is O (n ^ 2 * m ^ 2). For this question, 100 of the data can be AC. However, if the data volume increases, you need to change the method. In fact, after finding the maximum match, if (x-> y) is an edge in the maximum match, we first Delete this edge and cause y to be out of service. In this case, we can find an accesskey for x. If we can find the accesskey, we use another match to replace the match (x-> y). Therefore, (x-> y) is not required. Otherwise, (x-> y) is required. NOTE: If (x-> y) is required, link [y] = x is required. x matches y again to reach the maximum match. In addition, no matter whether (x->) is required, the source image must be restored.
Method 1: Brute Force:
VIEW CODE
#include
#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int mod=99999997;const double eps=1e-8;const double pi=acos(-1.0);const int inf=0x3fffffff;bool G[110][110];int link[110];int n,m;bool vis[110];bool match(int x){ for(int i=1;i<=m;i++) { if(G[x][i]&&(!vis[i])) { vis[i]=1; if(link[i]==-1||match(link[i])) { link[i]=x; return 1; } } } return 0;}int hungury(){ int ans=0; memset(link,-1,sizeof link); for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); if(match(i)) ans++; } return ans;}int link__[110];int main(){ int k,ca=0; while(cin>>n>>m>>k) { memset(G,0,sizeof G); while(k--) { int x,y; scanf("%d %d",&x,&y); G[x][y]=1; } int aa=hungury(); int ans=0; for(int i=1;i<=m;i++) link__[i]=link[i]; for(int i=1;i<=m;i++) { if(link__[i]+1) { int x=link__[i]; G[x][i]=0; if(hungury()!=aa) ans++; G[x][i]=1; } } printf("Board %d have %d important blanks for %d chessmen.\n",++ca,ans,aa); } return 0;}
Method 2: Find zengguang road at one time
VIEW CODE
#include
#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int mod=99999997;const double eps=1e-8;const double pi=acos(-1.0);const int inf=0x3fffffff;bool G[110][110];int link[110];int n,m;bool vis[110];bool match(int x){ for(int i=1;i<=m;i++) { if(G[x][i]&&(!vis[i])) { vis[i]=1; if(link[i]==-1||match(link[i])) { link[i]=x; return 1; } } } return 0;}int hungury(){ int ans=0; memset(link,-1,sizeof link); for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); if(match(i)) ans++; } return ans;}int main(){ int k,ca=0; while(cin>>n>>m>>k) { memset(G,0,sizeof G); while(k--) { int x,y; scanf("%d %d",&x,&y); G[x][y]=1; } int aa=hungury(); int ans=0; for(int i=1;i<=m;i++) { if(link[i]+1) { int x=link[i]; G[x][i]=0; link[i]=-1; memset(vis,0,sizeof vis); if(!match(x)) { ans++; link[i]=x; } G[x][i]=1; } } printf("Board %d have %d important blanks for %d chessmen.\n",++ca,ans,aa); } return 0;}