题意:给定一个有向无环图,求最少划分几条路径,使之能够覆盖所有点。
分析:这可以转化为DAG上的最小路径覆盖问题。
路径覆盖的定义:有向图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每条路径就是一个弱连通子集。
|最小路径覆盖| = 点数 - |最大匹配|,所以建图,用匈牙利算法求出最大匹配即可。
#include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include <iostream> using namespace std; typedef long long LL; const int maxn =125; int N; struct Edge{ int to,next; }edges[maxn<<2]; int head[maxn],tot; int linker[maxn]; bool used[maxn]; void init() { tot=0; memset(head,-1,sizeof(head)); } void AddEdge(int u,int v) { edges[tot].to = v; edges[tot].next = head[u]; head[u] = tot++; } bool dfs(int u){ int v,st,ed; for(int i=head[u];~i;i = edges[i].next){ v = edges[i].to; if(!used[v]){ used[v]=true; if(linker[v]==-1||dfs(linker[v])){ linker[v]=u; return true; } } } return false; } int hungary(){ int res=0; memset(linker,-1,sizeof(linker)); for(int u=1;u<=N;u++){ memset(used,0,sizeof(used)); if(dfs(u)) res++; } return res; } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int T,M,u,v,tmp; scanf("%d",&T); while(T--){ init(); scanf("%d%d",&N,&M); for(int i=1;i<=M;++i){ scanf("%d%d",&u,&v); AddEdge(u,v); } int res = N-hungary(); //求最小路径覆盖 printf("%d\n",res); } return 0; }