[24 network flow problem] minimum path covering problem - the maximum flow, bipartite graph matching

Minimum (disjoint) path coverage problems

Obviously you want to split the point, then we converted to a bipartite graph matching problem. On each side of a path \ ((u, v) \ ) corresponds to a \ (u \ to v '\ ) match. So long as the split point to establish a bipartite graph, the answer is the original number of nodes - maximum number of matches.

Consider how the program output. For each node of the original, we record the number of matching corresponding points of two of its participation in the new image. Obviously each path must be involved from a number of \ (1 \) is involved in a number of points to start is \ (1 \) end points. Then we can find a time to participate in a number of not yet treated as \ (1 \) points began to walk along the path can be, and this can be seen as a process of degradation of the search run.

#include <bits/stdc++.h>
using namespace std;
const int N = 16384, MAXN = 262144;
#define reset(x) memset(x,0,sizeof x)
struct graph
{
    int n,m,M,S,T,head[N],cur[N],dep[N],gap[N],q[N];
    long long ans;
    struct ed
    {
        int from,to,nxt,val;
    } edge[MAXN];
    void init(int n0,int m0,int S0,int T0)
    {
        n=n0,m=m0,S=S0,T=T0,M=1,reset(gap);
        reset(head),reset(cur),reset(dep),reset(q);
    }
    void make(int u,int v,int w)
    {
        edge[++M]=(ed) {u,v,head[u],w},head[u]=M;
    }
    int dfs(int u,int mx)
    {
        if (u==T)
            return mx;
        int num=0,f;
        for (int &i=cur[u],v; i; i=edge[i].nxt)
            if (dep[v=edge[i].to]==dep[u]-1 && (f=edge[i].val))
                if (edge[i].val-=(f=dfs(v,min(mx-num,f))), edge[i^1].val+=f, (num+=f)==mx)
                    return num;
        if (!--gap[dep[u]++])
            dep[S]=n+1;
        return ++gap[dep[u]],cur[u]=head[u],num;
    }
    void solve()
    {
        for (int i=1; i<=n; ++i)
            cur[i]=head[i];
        ans=0;
        for (gap[0]=n; dep[S]<=n; ans+=dfs(S,0x7fffffff));
    }
} g;

int n,m,t1,t2,t3,t4,vis[N],ch[N][2],deg[N];

int main()
{
    cin>>n>>m;
    g.init(2*n+2,0,2*n+1,2*n+2);
    for(int i=1; i<=m; i++)
    {
        cin>>t1>>t2;
        g.make(t1,t2+n,1);
        g.make(t2+n,t1,0);
    }
    for(int i=1; i<=n; i++)
    {
        g.make(2*n+1,i,1);
        g.make(i,2*n+1,0);
        g.make(n+i,2*n+2,1);
        g.make(2*n+2,n+i,0);
    }
    g.solve();
    for(int i=1; i<=m; i++)
    {
        if(g.edge[2*i].val==0)
        {
            ch[(g.edge[2*i].from-1)%n+1][deg[(g.edge[2*i].from-1)%n+1]++]=(g.edge[2*i].to-1)%n+1;
            ch[(g.edge[2*i].to-1)%n+1][deg[(g.edge[2*i].to-1)%n+1]++]=(g.edge[2*i].from-1)%n+1;
        }
    }
    for(int i=1; i<=n; i++)
    {
        if(vis[i])
            continue;
        if(deg[i]==0)
            cout<<i;
        if(deg[i]==1)
        {
            int p = i;
            cout<<p<<" ";
            vis[p]=1;
            p=ch[p][0];
            while(deg[p]>1)
            {
                vis[p]=1;
                cout<<p<<" ";
                if(vis[ch[p][0]])
                    p=ch[p][1];
                else
                    p=ch[p][0];
            }
            vis[p]=1;
            cout<<p<<" ";
        }
        cout<<endl;
    }
    cout<<n-g.ans<<endl;
}

Guess you like

Origin www.cnblogs.com/mollnn/p/11719148.html