给你一些点,和一些边,如果把一个点安装保护装置,那么与他直接相连的点就可以被保护,题目问的是最少安装多少个点能让所有的点都被保护。
思路:
这是最基础的二分图最少定点覆盖,对于可以保护的点,我们只要找到最大的匹配次数,也就是最少的安置个数就行了,直接一遍匈牙利,注意的一点是建图的时候记得建双向边,最后答案要除以2,因为a->b b->a 匹配数是2。
#include<stdio.h> #include<string.h> #define N_node 1550 #define N_edge 2255000 typedef struct { int to ,next; }STAR; STAR E[N_edge]; int list[N_node] ,tot; int mk_dfs[N_node] ,mk_gx[N_node]; void add(int a ,int b) { E[++tot].to = b; E[tot].next = list[a]; list[a] = tot; } int DFS_XYL(int x) { for(int k = list[x] ;k ;k = E[k].next) { int to = E[k].to; if(mk_dfs[to]) continue; mk_dfs[to] = 1; if(mk_gx[to] == -1 || DFS_XYL(mk_gx[to])) { mk_gx[to] = x; return 1; } } return 0; } int main () { int n ,i ,ans ,nn ,from ,to; while(~scanf("%d" ,&n)) { memset(list ,0 ,sizeof(list)) ,tot = 1; for(i = 1 ;i <= n ;i ++) { scanf("%d:(%d)" ,&from ,&nn); while(nn--) { scanf("%d" ,&to); add(from + 1 ,to + 1); add(to + 1 ,from + 1); } } memset(mk_gx ,255 ,sizeof(mk_gx)); ans = 0; for(i = 1 ;i <= n ;i ++) { memset(mk_dfs ,0 ,sizeof(mk_dfs)); ans += DFS_XYL(i); } printf("%d " ,ans / 2); } return 0; }