code vs [网络流24题]最小路径覆盖问题

1904 最小路径覆盖问题

 时间限制: 2 s
 空间限制: 256000 KB
 题目等级 : 大师 Master
题解
题目描述 Description

给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个
顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶
点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少
的路径覆盖。
设计一个有效算法求一个有向无环图G 的最小路径覆盖。

对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。

输入描述 Input Description

第1 行有2个正整数n和m。n是给定有向无环图
G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。

输出描述 Output Description

最少路径数。

样例输入 Sample Input

11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11

样例输出 Sample Output

3


题解:

此题的关键是:最小路径覆盖=原图点数-最大匹配

那么最大匹配可以转化为求最大流。那么如何建图呢?拆点。

把每个点拆成两个,一个表示进,一个表示出

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int point[2100],next[2000003],v[2000003],remain[2000003];
int deep[2100],cur[2100],n,m,tot;
const int inf=1e9;
void add(int x,int y,int z)
{
  tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
  tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
bool bfs(int s,int t)
{
	memset(deep,0x7f,sizeof(deep));
	for (int i=s;i<=t;i++)
	 cur[i]=point[i];
	deep[s]=0;
	queue<int> p;
	p.push(s);
	while (!p.empty())
	 {
	  int now=p.front(); p.pop();
	  for (int i=point[now];i!=-1;i=next[i])
	   if (deep[v[i]]>inf&&remain[i])
	    deep[v[i]]=deep[now]+1,p.push(v[i]);
	 }
	return deep[t]<inf;
}
int dfs(int now,int t,int limit)
{
	if (!limit||now==t)  return limit;
	int flow=0,f;
	for (int i=cur[now];i!=-1;i=next[i])
	 {
	 	cur[now]=i;
	 	if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(limit,remain[i]))))
	 	 {
	 	 	flow+=f; limit-=f;
	 	 	remain[i]-=f; remain[i^1]+=f;
	 	 	if (!limit) break;
	 	 }
	 }
	return flow;
}
int dinic(int s,int t)
{
 int ans=0;
 while (bfs(s,t))
  ans+=dfs(s,t,inf);
 return ans;
}
int main()
{
  tot=-1;
  memset(point,-1,sizeof(point));
  memset(next,-1,sizeof(next));
  scanf("%d%d",&n,&m);
  for (int i=1;i<=m;i++)
   {
   	int x,y; scanf("%d%d",&x,&y);
   	add(x,y+n,inf);
   }
  for (int i=1;i<=n;i++) add(0,i,1);
  for (int i=1;i<=n;i++) add(n+i,2*n+1,1);
  printf("%d",n-dinic(0,2*n+1));
}


你可能感兴趣的:(code vs [网络流24题]最小路径覆盖问题)