题目大意:就是在单向 的街道上,问要有几个士兵才能把所有的街道的交叉点(节点)访问完,因题目说是无环图(the town's streets form no cycles)所以可以用最小路径覆盖来做
思路:因为是有向无环图,所以求以最少的人来访问全部的交叉点,就可以用最小路径覆盖做,做法:把出发点和终点都拆成2个节点,利用出发点和终点进行匹配(数组的含义,因为是以所有的交叉口的数目来开数组的),这就是所谓的拆分节点变成二分图,从而可以求出最大匹配,利用公式求出最后的最小路径覆盖
注意:路径的含义!
program:
#include<iostream>
#define N 121
using namespace std;
bool mat[N][N];
bool vis[N];
int link[N];
int t,n,k,x,y;
int getnum(int i)
{
for(int j=1;j<=n;j++)
{
if(mat[i][j]==1&&vis[j]==false)
{
vis[j]=true;
if(link[j]==false||getnum(link[j])==1)
{
link[j]=i;
return 1;
}
}
}
return 0;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
memset(mat,false,sizeof(mat));
while(k--)
{
cin>>x>>y;
mat[x][y]=true; //这个数组就是出发点和终点的匹配,看!n的循环这个意思就漏出来的啦
}
int num=0;
memset(link,0,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i))
num++;
}
cout<<(n-num)<<endl;
}
return 0;
}
PS:
二分图最大独立集=n-m
二分图最小顶点覆盖=m
二分图最小路径覆盖=n-m
最小边覆盖 最小路径覆盖
这个是在原图是二分图上进行的
最小路径覆盖和
然后最小路径覆盖是n-m,n为原图的点的个数,m为新造二分图的最大匹配。证明也是特别简单的,根据定义最小路径覆盖里要求同一个点只可以属于一条路径,即路径时不可以开叉的,如果在二分图里选两条有公共点的边那么反应在原图上就是路径有岔路了,所以二分图里选的边必须是无公共交点的,这就是转化到最大匹配了。