【线性规划与网络流24题 3】最小路径覆盖
Time Limit:10000MS Memory Limit:65536K
Total Submit:35 Accepted:14
Case Time Limit:1000MS
Description
给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图G 的最小路径覆盖。
对于给定的给定有向无环图G,编程找出 G的一个最小路径覆盖。
由于本OJ无Special Judge , 所以只需要输出路径的条数
Input
第1 行有 2个正整数 n和 m。n是给定有向无环图(0<n<=150,0<=m<=n*n)
G 的顶点数, m是G 的边数。 接下来的 m行, 每行有 2 个正整数 i和 j, 表示一条有向边(i,j)。
Output
一行,包含一个整数,表示最少路径数
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
Source
感谢 Wo_ai_WangYuan 修改题目并放上数据
网络流模型
我们先将n个点分成x,y两个集合,如果u到v有一条边,就将u放在x集合,v放在y集合
然后就是网络流建图,这里先给出建图方式
设源点为op,汇点为ed,那么op与x集合所有点连一条容量为1的边(即x中的每个点只能用一次)
x集合与y集合中能互相到达的两点连一条容量>=1的边,最后y集合中每一个点与ed连一条容量为1的边(即y中的每个点只能用一次)
这样建图后求出来的最大流就一定是最大匹配数(想一想为什么)
ans=n-最大匹配,如果无匹配,显然要n条路径才能覆盖所有点,两个点匹配意味着将可以把它们用一条路径覆盖,路径数就可以减1
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=305,inf=1e9;
int n,m, g[maxn][maxn],op,ed;
int dis[maxn],vd[maxn];
int dfs(int u,int flow){
if(u==ed)return flow;
int v,temp,delta=0;
for(v=1;v<=ed;v++)
if(g[u][v]&&dis[u]==dis[v]+1){
temp=dfs(v,min(flow-delta,g[u][v]));
g[u][v]-=temp;
g[v][u]+=temp;
delta+=temp;
if(delta==flow||dis[op]>=ed)return delta;
}
if(dis[op]>=ed)return delta;
vd[dis[u]]--;
if(vd[dis[u]]==0)dis[op]=ed;
dis[u]++;
vd[dis[u]]++;
return delta;
}
int main(){
cin>>n>>m;
int i,j,x,y,ans=0;
op=n+n+1,ed=op+1;
for(i=1;i<=m;i++){
cin>>x>>y;
g[op][x]=1;
g[x][y+n]=1;
g[y+n][ed]=1;
}
while(dis[op]<ed)ans+=dfs(op,inf);
cout<<n-ans;
}