swust1738: 最小路径覆盖问题

来源:互联网 发布:vc网络编程开发与实战 编辑:程序博客网 时间:2024/04/27 19:30

链接:http://www.oj.swust.edu.cn/problem/show/1738

题意:中文题。

分析:网络流24题第三题。最小路径覆盖,我们可以转换成二分图匹配去做,将点i拆成点i和点i+n,每一条边(i,j)变成i与j+n相连,然后匹配。为什么能转呢?我们可以先将这n个点看成是孤立的,也就是n条路径覆盖,然后我们试着加边,每加一条边将一对路径的首尾连起来那么路径数就少了一条,那么最后答案ans=n-最大匹配数。还不清楚的话可以自己画画图理解下,输出路径的话沿着匹配的方向就能输出了。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<bitset>#include<math.h>#include<vector>#include<string>#include<sstream>#include<stdio.h>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=305;const int MAX=1000000100;const int mod=100000000;const int MOD1=1000000007;const int MOD2=1000000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=998244353;const int INF=1000000010;const double pi=acos(-1.0);typedef double db;typedef unsigned long long ull;int tot,u[N],v[N*N],cap[N*N],flow[N*N],pre[N*N];void add(int a,int b,int c,int f) {    v[tot]=b;cap[tot]=c;flow[tot]=f;pre[tot]=u[a];u[a]=tot++;}bool q[N];int n,d[N],dis[N],head[N];bool bfs(int a,int b) {    int i,l=1,r=1;    memset(q,0,sizeof(q));    d[1]=a;q[a]=1;dis[a]=0;    for (;l<=r;l++)        for (i=u[d[l]];i!=-1;i=pre[i])        if (!q[v[i]]&&cap[i]>flow[i]) q[v[i]]=1,d[++r]=v[i],dis[v[i]]=dis[d[l]]+1;    return q[b];}int dfs(int a,int b,int en) {    if (a==en||b==0) return b;    int ret=0,f;    for (int& i=u[a];i!=-1;i=pre[i])    if (dis[v[i]]==dis[a]+1&&(f=dfs(v[i],min(b,cap[i]-flow[i]),en))>0) {        flow[i]+=f;flow[i^1]-=f;        b-=f;ret+=f;        if (b==0) break ;    }    return ret;}void out(int a) {    printf("%d ", a);q[a]=1;    for (int i=u[a];i!=-1;i=pre[i])    if (v[i]!=0&&v[i]!=2*n+1&&flow[i]&&!q[v[i]-n]) out(v[i]-n);}int main(){    int a,b,i,m,ans=0;    scanf("%d%d", &n, &m);    tot=0;memset(u,-1,sizeof(u));    for (i=1;i<=m;i++) {        scanf("%d%d", &a, &b);        add(a,b+n,1,0);add(b+n,a,0,0);    }    for (i=1;i<=n;i++) {        add(0,i,1,0);add(i,0,0,0);        add(i+n,2*n+1,1,0);add(2*n+1,i+n,0,0);    }    for (i=0;i<=2*n+1;i++) head[i]=u[i];    while (bfs(0,2*n+1)) {        ans+=dfs(0,INF,2*n+1);        for (i=0;i<=2*n+1;i++) u[i]=head[i];    }    memset(q,0,sizeof(q));    for (i=1;i<=n;i++)    if (!q[i]) {        out(i);printf("\n");    }    printf("%d\n", n-ans);    return 0;}


0 0
原创粉丝点击