NKOI 1938 最小路径覆盖

来源:互联网 发布:大疆官网模拟软件p 编辑:程序博客网 时间:2024/06/06 15:35

【线性规划与网络流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;}

0 0