Note:
X. x
. X.
. X.For example, in figure X on the left, you can use a laser to destroy monsters. At a time, you can destroy all monsters in the same row or column. You can only ask how many times to finish killing all monsters.
Idea: Consider the X and Y coordinates as the left and right sets respectively. If the two coordinates are related, create an edge.
The final result is least vertex coverage.
Proof of correctness: the coordinates of each monster are determined by a pair of X and Y. In the bipartite graph, each side represents a pair of coordinate points, so you only need to overwrite all the sides.
Code:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 using namespace std; 7 8 const int maxn = 505; 9 10 struct Node {11 int to, next;12 }p[10005];13 14 int head[10005];15 16 int tot;17 18 int X[maxn];19 int x_cnt;20 int vis[maxn];21 int link[maxn];22 23 void AddEdge(int u, int v) {24 p[tot].to = v;25 p[tot].next = head[u];26 head[u] = tot ++;27 }28 29 bool Find(int u) {30 for(int i = head[u]; i; i = p[i].next) {31 int v = p[i].to;32 if(!vis[v]) {33 vis[v] = 1;34 if(link[v] == -1 || Find(link[v])) {35 link[v] = u;36 return true;37 }38 }39 }40 return false;41 }42 int n;43 44 int solve() {45 int cnt = 0;46 memset(link, -1, sizeof(link));47 memset(vis, 0, sizeof(vis));48 if(Find(X[0])) cnt++;49 for(int i = 1; i < x_cnt; i++) {50 if(X[i] == X[i - 1]) continue;51 memset(vis, 0, sizeof(vis));52 if(Find(X[i])) cnt++;53 }54 return cnt;55 }56 57 int main() {58 int k;59 int u, v;60 //freopen("3041.txt","r",stdin);61 while(EOF != scanf("%d %d",&n, &k)) {62 tot = 1;63 x_cnt = 0;64 memset(head, 0, sizeof(head));65 //memset(X, 0, sizeof(X));66 for(int i = 0; i < k; i++) {67 scanf("%d %d",&u, &v);68 AddEdge(u, v);69 X[x_cnt++] = u;70 }71 sort(X, X + x_cnt);72 printf("%d\n",solve());73 }74 return 0;75 }View code