The main idea: in a n*m grid, there are k targets, you can now select a row or column to eliminate all the targets on it, to find the minimum number of choices and selection method.
Title Analysis: Classic minimum point coverage problem, and output a minimum point coverage set. After you find the maximum match, mark with an uncovered X-dot, covering not covered with overwrite, not covered ... , and the points marked in the last X and Y are the minimum point overlay sets.
The code is as follows:
# include<iostream># include<cstdio># include<cstring># include<algorithm>using namespace std;# define REP (i,s,n) for (int i=s;i<n;++i) # define CL (A, B) memset (A,b,sizeof (a)) # define CLL (A,b,n) Fill (a,a+n,b) const int n=1005;struct edge{int to,nxt;}; Edge e[n*n];int link[n],visx[n],visy[n],vis[2*n],mark[n];int cnt,n,m,head[n];void Add (int u,int v) {e[cnt].to=v; E[cnt].nxt=head[u]; head[u]=cnt++;} void dfs1 (int x) {visx[x]=1; for (int i=head[x];i!=-1;i=e[i].nxt) {int y=e[i].to; if (Visy[y]) continue; Visy[y]=1; DFS1 (Link[y]); }}bool dfs (int x) {for (int i=head[x];i!=-1;i=e[i].nxt) {int y=e[i].to; if (Vis[y]) continue; Vis[y]=1; if (link[y]==-1| | DFS (Link[y])) {link[y]=x; return true; }} return false;} int match () {int res=0; REP (i,1,n+1) {CL (vis,0); if (Dfs (i)) ++res; } return res; int main () {int a,b,k; while (scanf ("%d%d%d", &n,&m,&k) && (n+m+k)) {cnt=0; CL (head,-1); CL (link,-1); CL (mark,0); CL (visx,0); CL (visy,0); while (k--) {scanf ("%d%d", &a,&b); Add (A, b); } int Ans=match (); REP (i,1,m+1) if (link[i]!=-1) mark[link[i]]=1; REP (i,1,n+1) if (!mark[i]) DFS1 (i); printf ("%d", ans); REP (i,1,n+1) if (!visx[i]) printf ("r%d", I); REP (i,1,m+1) if (Visy[i]) printf ("c%d", I); printf ("\ n"); } return 0;}
UVA-11419 SAM I AM (minimum point coverage)