HDU

题意:一个城镇有n个路口,由一些单向马路连接。现在要安排一些伞兵降落在某些路口上,清查所有的路口。
一个伞兵可以沿着马路一路清查过去。清查过程中不能有两个伞兵同时清查一个路口(应该是为了防止暴露)。
给定城镇的线路,求最少需要几个人伞兵就能清查所有的路口。
第一个整数表示测试数据的组数。
对于每组测试数据,第一行一个整数n表示路口数量。
第三行一个整数m表示马路的数量
接下来m行,每行两个整数表示一条单向路径。
输出:最少伞兵个数
思路: 有向图的最小路径覆盖问题 , 结论:顶点数-最小点覆盖数 = 顶点数 - 最大匹配数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e3+5;
const int maxm = 1e6+5;
struct Edge
{
    int v,next;
}edge[maxm];
int n,m;
int top ;
int head[maxn];
int vis[maxn];
int match[maxn];
void add(int u,int v){
    edge[top].v = v;
    edge[top].next = head[u];
    head[u] = top++;
}
bool dfs(int u){
    for(int i = head[u]; ~i;i = edge[i].next){
        int v = edge[i].v;
        if(!vis[v]){
            vis[v] = 1;
            if(!match[v]||dfs(match[v])){
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}
int hungary(){
    int res = 0;
    memset(match,0,sizeof(match));
    for(int i =1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i)) res++;
    }
    return res;
}
void init(){
    top = 0;
    memset(head,-1,sizeof(head));
}
int main(){
    int T;
    cin>>T;
    while(T--){
        init();
        cin>>n>>m;
        for(int i = 1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
        }
        int ans = hungary();
        cout<<n-ans<<endl;
    }
}
原文地址:https://www.cnblogs.com/Tianwell/p/11341111.html