HDU - 1151 Air Raid(最小路径覆盖)
题意:一个城镇有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; } }