Solutions of the shortest path problem] [coverage problems (network flow)

Minimum path cover problem

The final way that consider what is the path covered, and many apparently many points strand (nonsense), but learned of biological peptide and proteins compulsory a person can be found, the number of paths = \ (n-m-'\) , \ (n-\) is the number of points, \ (m '\) is elected number of sides.

Here \ (n-\) is a fixed value, the selected transition problem most edge \ (m '\) , selected such that there is no side common start or end point.

That is, as a point of start and end at the same time, but can not be simultaneously connected to two edges. Consider the side is a starting point, that is, an end point, and can only be a starting point and match, each successfully matched to a description can be selected on an edge .

= Start and end points match bipartite graph matching the maximum flow = = \ (m '\)

In summary, a method can be obtained: the selected edge matching start and end =

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

int cnt=1;
const int inf=0x3f3f3f3f;
int S,T,m,n;

struct E{
      int to,nx,w;
      E(){to=nx=w=0;}
      E(const int&a,const int&b,const int&c){to=a;nx=b;w=c;}
}e[48005];
int head[355];
inline void add(const int&fr,const int&to,const int&w,const int&f=1){
      e[++cnt]=E(to,head[fr],w);
      head[fr]=cnt;
      if(f) add(to,fr,0,0);
}


const int maxn=355;
int sum=0;
queue < int > q;
int d[maxn],cur[maxn];
inline bool bfs(){
      for(register int t=1;t<=n+n+2;++t) d[t]=0,cur[t]=head[t];
      d[S]=1;q.push(S);
      while(q.size()){
        register int now=q.front();
        q.pop();
        for(register int t=head[now];t;t=e[t].nx){
          if(e[t].w>0&&d[e[t].to]==0){
            d[e[t].to]=d[now]+1;
            q.push(e[t].to);        
          }
        }
      }
      return d[T];
      
}

int dfs(const int&now,int fl){
      if(now==T||fl==0)return fl;
      register int ret=0;
      for(register int&t=cur[now];t;t=e[t].nx){
        if(e[t].w>0&&d[e[t].to]==d[now]+1){
          int d=dfs(e[t].to,min(e[t].w,fl));
          e[t].w-=d;e[t^1].w+=d;ret+=d;fl-=d;
        }
      }
      return ret;
}


inline int dinic(){
      int ret=0;
      while(bfs())ret+=dfs(S,inf);
      return ret;
}

namespace getans{
#define pb push_back
      vector < vector < int > > ve;
      const int maxn=155;
      int r[maxn];
      int dr[maxn];
      inline void add(int fr,int to){
        r[to]=fr;
        ++dr[to];++dr[fr];
      }
      int n;
      inline void main(const int&a){
        vector < int > temp;n=a;
        for(register int t=1;t<=n;++t){
          if(dr[t]==1&&r[t]){
            vector < int > ().swap(temp);
            int now=t;
            while(r[now]) temp.pb(now),now=r[now];
            temp.pb(now);reverse(temp.begin(),temp.end());
            ve.pb(temp);
          }
          if(!dr[t]){
            vector < int > (t).swap(temp);
            ve.pb(temp);
          }
        }
        for(auto t:ve){
          for(auto f:t)
            printf("%d ",f);
          putchar('\n');
        }
      }
}

int main(){
      
      n=qr();m=qr();
      S=n+n+1;T=n+n+2;
      for(register int t=1;t<=n;++t)
        add(S,t,1),add(t+n,T,1);
      for(register int t=1;t<=m;++t){
        register int t1=qr(),t2=qr();
        add(t1,t2+n,1);
      }
      int ans=n-dinic();
      for(register int t=1;t<=n;++t)
        for(register int i=head[t];i;i=e[i].nx)
          if(e[i].w==0&&e[i].to>=n&&e[i].to<=n+n){
            getans::add(t,e[i].to-n);
            break;
          }
      getans::main(n);
      printf("%d\n",ans);      
      return 0;
}

Guess you like

Origin www.cnblogs.com/winlere/p/11237210.html