HDU 1151 Air Raid(最小路径覆盖)

来源:互联网 发布:超市管理数据库设计 编辑:程序博客网 时间:2024/06/08 07:15


题目大意:

在一个城镇,有m个路口,和n条路,这些路都是单向的,而且路不会形成环,现在要弄一些伞兵去巡查这个城镇,伞兵只能沿着路的方向走,问最少需要多少伞兵才能把所有的路口搜一遍。


解题思路:

这个题目就转换成求解有向无环图的最小路径覆盖问题了。

        一个结论:有向无环图的最小路径覆盖=该图的顶点数-该图(原图)的最大匹配。


而路径覆盖的定义就是:

在有向图中找一些路径,使之覆盖了图中的所有顶点,就是任意一个顶点都跟那些路径中的某一条关联,且任何一个顶点

有且只有一个与之关联;一个单独的顶点是一跳路径……最小路径覆盖就是最少的路径覆盖数。


最小边覆盖与最小路径覆盖的联系与区别:http://blog.csdn.net/wall_f/article/details/8187144


#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;/* **************************************************************************//二分图匹配(匈牙利算法的DFS实现)//初始化:g[][]两边顶点的划分情况//建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配//g没有边相连则初始化为0//uN是匹配左边的顶点数,vN是匹配右边的顶点数//调用:res=hungary();输出最大匹配数//优点:适用于稠密图,DFS找增广路,实现简洁易于理解//时间复杂度:O(VE)//***************************************************************************///顶点编号从0开始的const int MAXN=150;int uN,vN;//u,v数目int g[MAXN][MAXN];int linker[MAXN];bool used[MAXN];bool dfs(int u)//从左边开始找增广路径{    int v;    for(v=0;v<vN;v++)//这个顶点编号从0开始,若要从1开始需要修改      if(g[u][v]&&!used[v])      {          used[v]=true;          if(linker[v]==-1||dfs(linker[v]))          {//找增广路,反向              linker[v]=u;              return true;          }      }    return false;//这个不要忘了,经常忘记这句}int hungary(){    int res=0;    int u;    memset(linker,-1,sizeof(linker));    for(u=0;u<uN;u++)    {        memset(used,0,sizeof(used));        if(dfs(u)) res++;    }    return res;}//******************************************************************************/int main(){    int k;    int n;    int u,v;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&k);        memset(g,0,sizeof(g));        while(k--)        {            scanf("%d%d",&u,&v);            u--;            v--;            g[u][v]=1;        }        uN=vN=n;        printf("%d\n",n-hungary());    }    return 0;}


原创粉丝点击