「网络流 24 题」最小路径覆盖
写在前面:
这是今天第二篇博客,还是网络流!!
题目大意:
给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个顶 点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶点 开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少的路 径覆盖。
设计一个有效算法求一个有向无环图G的最小路径覆盖。
正解:
可恶,整场比赛就只剩这道裸一点了!😠
很明显,我们把点拆成两部分,然后,我们直接来个hungary算法来求出最大流路径,OK!完工!
输出的话,不会还有人不会吧?(不是吧不是吧?)
照这边输出,也就是
f
o
r
(
i
n
t
a
n
s
=
i
;
a
n
s
;
a
n
s
=
n
x
t
[
a
n
s
]
)
for(int ans=i;ans;ans=nxt[ans])
for(intans=i;ans;ans=nxt[ans])
然后挨个输出得了。
还有人说:啊,我不会匈牙利!
很简单,算法大意就是贪心,找最小或最大边,如有更佳,反悔!不干了!
来!!!
code:
#include<bits/stdc++.h>
using namespace std;
int n,m,sum;
int mp[201][201];
int dis[201],vis[201];
int cur[201],nxt[201];
bool hungary(int s)
{
for(int i=1; i<=n; i++)
{
if(!mp[s][i]||vis[i]) continue;
vis[i]=1;
if(!dis[i]||hungary(dis[i]))
{
dis[i]=s;
return true;
}
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
sum=n;
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=1;
}
for(int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(hungary(i)) sum--;
}
for(int i=1; i<=n; i++)
{
cur[i]=dis[i];
nxt[dis[i]]=i;
}
for(int i=1; i<=n; i++)
{
if(cur[i]) continue;
for(int ans=i;ans;ans=nxt[ans])
{
if(ans==nxt[ans])
{
printf("%d",ans);//这里要特判,不然会报错!
//最后一个不能输出空格!!!
continue;
}
printf("%d ",ans);
}
printf("\n");
}
printf("%d",sum);
}
\\由于是Special Judge,只需方案数对就行