POJ1422 最小路径覆盖

来源:互联网 发布:virtualbox知乎 编辑:程序博客网 时间:2024/05/17 01:41
题意:
     一个战场,往战场上投放伞兵,每个伞兵不能后退,只能往前走,问你最少多少个伞兵可以吧所有的点都占领。


思路:

     这个题是最小路径覆盖,最小路径覆盖 = n - 最大匹配数,首先说下什么是最小路径覆盖,给你一个有向无环图,问你最少用多少条无返回路径可以覆盖所有点,再说下为什么是n - 最大匹配数,想下,假如没有边,那么就是每个点放一个伞兵,假如只有一条边,那么就是n - 1,两条的或有可能是 n - 1,也有可能是 n - 2,加入是 a->b->c 就是n - 1,如果是 a->b ,a-c,或者a -> b ,d ->c就是n - 2,这样就用到了二分匹配的性质,只要能匹配上一队就少了一个伞兵,所以最少的伞兵 = n - 最大匹配数。  


#include<stdio.h>#include<string.h>#define N_node 150#define N_edge 150typedef struct{   int to ,next;}STAR;STAR E[N_edge];int list[N_node] ,tot;int mk_gx[N_node] ,mk_dfs[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 t ,n ,m ,i;    int a ,b;    scanf("%d" ,&t);    while(t--)    {       scanf("%d" ,&n);       scanf("%d" ,&m);       memset(list ,0 ,sizeof(list));       tot = 1;       for(i = 1 ;i <= m ;i ++)       {          scanf("%d %d" ,&a ,&b);          add(a ,b);       }       memset(mk_gx ,255 ,sizeof(mk_gx));       int sum = 0;       for(i = 1 ;i <= n ;i ++)       {          memset(mk_dfs ,0 ,sizeof(mk_dfs));          sum += DFS_XYL(i);       }       printf("%d\n" ,n - sum);    }    return 0;}

0 0
原创粉丝点击