最短経路問題のソリューション] [カバレッジの問題(ネットワークフロー)

最小パス被覆問題

パスが覆われているかを考え、最終的な方法は、多くの明らかに多くのポイント鎖(ナンセンス)が、生物学的ペプチドを学び、タンパク質義務者は、パスの数を見つけることができます= \(N-M - '\) \ (N- \)ポイントの数であり、\(M「\)に選出された辺の数。

ここで\(N- \)固定値、選択された遷移問題最もエッジである\(M「\)、NO側共通の開始または終了点が存在しないように選択。

それは、同時に開始および終了点として、であるが、同時に2つのエッジに接続することができません。すなわち、であり、出発点である側を検討エンドポイント、及びだけうまく説明に一致し、各エッジ上で選択することができ、開始点と一致することができます

=開始点と終了点は、最大流量= =マッチング部グラフ一致\(M「を\)

要約すると、方法を得ることができる:選択したエッジは、開始と終了と一致します=

//@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;
}

おすすめ

転載: www.cnblogs.com/winlere/p/11237210.html
おすすめ