1、一个有向无环图(DAG),M个点,K条有向边,求DAG的最小路径覆盖数
2、DAG的最小路径覆盖数=DAG图中的节点数-相应二分图中的最大匹配数
3、
/* 顶点编号从0开始的 邻接矩阵(匈牙利算法) 二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式) 初始化:g[][]两边顶点的划分情况 建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配 g没有边相连则初始化为0 uN是匹配左边的顶点数,vN是匹配右边的顶点数 左边是X集,右边是Y集 调用:res=hungary();输出最大匹配数 优点:适用于稠密图,DFS找增广路,实现简洁易于理解 时间复杂度:O(VE) */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=512; int uN,vN;//u,v 的数目,使用前面必须赋值 int g[MAXN][MAXN];//邻接矩阵,记得初始化 int linker[MAXN];//linker[v]=u,表示v(右边Y集合中的点)连接到u(左边X集合中的点) bool used[MAXN]; bool dfs(int u){//判断以X集合中的节点u为起点的增广路径是否存在 for(int v=0;v<vN;v++)//枚举右边Y集合中的点 if(g[u][v]&&!used[v]){//搜索Y集合中所有与u相连的未访问点v used[v]=true;//访问节点v if(linker[v]==-1||dfs(linker[v])){//是否存在增广路径 //若v是未盖点(linker[v]==-1表示没有与v相连的点,即v是未盖点),找到增广路径 //或者存在从与v相连的匹配点linker[v]出发的增广路径 linker[v]=u;//设定(u,v)为匹配边,v连接到u return true;//返回找到增广路径 } } return false; } int hungary(){//返回最大匹配数(即最多的匹配边的条数) int res=0;//最大匹配数 memset(linker,-1,sizeof(linker));//匹配边集初始化为空 for(int u=0;u<uN;u++){//找X集合中的点的增广路 memset(used,false,sizeof(used));//设Y集合中的所有节点的未访问标志 if(dfs(u))res++;//找到增广路,匹配数(即匹配边的条数)+1 } return res; } int main(){ int i,ans; int K,M; int u,v; int T; scanf("%d",&T); while(T--){ scanf("%d%d",&M,&K); uN=M;//匹配左边的顶点数 vN=M;//匹配右边的顶点数 memset(g,0,sizeof(g));//二分图的邻接矩阵初始化 for(i=0;i<K;++i){ scanf("%d%d",&u,&v); g[--u][--v]=1;//顶点编号从0开始的 } ans=M-hungary(); printf("%d ",ans); } return 0; }