最小费用最大流模板(存边)

来源:互联网 发布:信用证是什么意思知乎 编辑:程序博客网 时间:2024/06/06 21:40

函数功能介绍:

Addedge(from,to,w,res) 添加一条 x->y,费用为w,残量为res的边,并一起添加其反向边,由于从0号开始,相邻两个数代表的边互为反向边(即i号边的反向边是 i^1)。

spfa.init(N)初始化点数N

spfa.find(S,T) 在 源点为S,汇点为T的图中寻找最小费用增广路,i号点的前驱边编号存在Path[i]中

代码如下(以nkoj 1589为例):

#include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<algorithm> #define LL long long #define CLEAR(xxx) memset(xxx,0,sizeof(xxx))    using namespace std;            const int inf=1e9;       const int maxn=1000+5;       int N,n,m,maxflow,mincost,last[maxn];   inline void _read(int &x){           char ch=getchar(); bool mark=false;           for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;           for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';           if(mark)x=-x;       }       struct Edge{     int from,to,res,w,Next;     Edge(int from,int to,int w,int res,int Next):from(from),to(to),w(w),res(res),Next(Next){} }; vector<Edge> edge; void Addedge(int from,int to,int w,int res){     edge.push_back(Edge(from,to,w,res,last[from]));     last[from]=edge.size()-1;     edge.push_back(Edge(to,from,-w,0,last[to]));     last[to]=edge.size()-1; }    int path[maxn], dist[maxn];            bool vis[maxn];        struct SPFA{           int  n;                void init(int n){         this->n =n;         memset(last,-1,sizeof(last));     }                              bool find(int s,int t){               int i;               CLEAR(vis);                for(i=1;i<=n;i++) dist[i]=inf;         memset(path,-1,sizeof(path)) ;              dist[s]=0;  path[s]=0 ;vis[s]=true;           queue <int> q;  q.push(s);               while(!q.empty()){                   int x=q.front();                   q.pop();vis[x]=false;               for(i=last[x];i!=-1;i=edge[i].Next){                    Edge& e=edge[i];                         if(e.res>0&&dist[x]+e.w<dist[e.to]){                           dist[e.to]=dist[x]+e.w;                     path[e.to]=i;                           if(!vis[e.to]){                               q.push(e.to) ;                               vis[e.to]=true;                           }                       }                    }               }           return dist[t]<inf;             }       }spfa;   void Addflow(int s,int t){     int flow=inf,i;     for(i=t; i!=s&&edge[path[i]].from!=0;i=edge[path[i]].from)         flow=min(flow,edge[path[i]].res);     maxflow+=flow;     mincost+=dist[t];     for(i=t;i!=s;i=edge[path[i]].from){         int x=path[i];         edge[x].res-=flow;         edge[x^1].res+=flow;     } }   int main(){     int i,j,k,x,y,z,cnt=0;     N=maxflow=mincost=0;     _read(n); _read(m);     spfa.init(N=n+2);    for(i=1;i<=m;i++){         _read(x); _read(y); _read(z);         Addedge(x,y,z,1);          Addedge(y,x,z,1);    }     Addedge(N-1,1,0,2);     Addedge(n,N,0,2);     while(spfa.find(N-1,N))Addflow(N-1,N);     cout<<mincost<<endl;     return 0;}   



#include<cstdio>#include<iostream>#include<algorithm>#include<cstdlib>#include<cstring>#include<queue>using namespace std;const long long inf=1000000000;long long n,p,tk,tm,wk,wm;long long N;long long maxflow;long long mincost;long long tot_edge=0;long long flow,cost;long long dis[10005],path[10005];long long a[10005];bool flag[10005];struct line{long long from,to,len,remain,fan;};line edge[5000005];long long last[10005],_next[5000005];void add_edge(long long x,long long y,long long l,long long acc){tot_edge++;edge[tot_edge].from=x;edge[tot_edge].to=y;edge[tot_edge].len=l;edge[tot_edge].remain=acc;edge[tot_edge].fan=tot_edge+1;_next[tot_edge]=last[x];last[x]=tot_edge;tot_edge++;edge[tot_edge].from=y;edge[tot_edge].to=x;edge[tot_edge].len=-l;edge[tot_edge].remain=0;edge[tot_edge].fan=tot_edge-1;_next[tot_edge]=last[y];last[y]=tot_edge;}bool findpath(){queue<long long> q;    long long i,j,now;    for(i=1;i<=N+2;i++){ dis[i]=inf; path[i]=-1;flag[i]=false;}    dis[N+1]=path[N+1]=0;flag[N+1]=true; q.push(N+1);    while(q.size()){        j=q.front();        q.pop();flag[j]=false;        for(long long h=last[j];h;h=_next[h]){        int v=edge[h].to;        if(edge[h].remain&&(dis[v]>dis[j]+edge[h].len)){        dis[v]=dis[j]+edge[h].len;        path[v]=h;        if(flag[v]==false){        flag[v]=true;        q.push(v);}}}     }     if(dis[N+2]<inf)return true;  else return false; }void addflow(){long long flow,cost,i;flow=inf;cost=0;i=N+2;while((i!=N+1)&&(path[i]!=0)){flow=min(flow,edge[path[i]].remain);cost+=edge[path[i]].len;   //edge[edge[path[i]].fan].len=-edge[edge[path[i]].fan].len;i=edge[path[i]].from;} maxflow+=flow; mincost+=flow*cost;i=N+2;while(i!=N+1){edge[path[i]].remain-=flow;edge[edge[path[i]].fan].remain+=flow;i=edge[path[i]].from;}}int main(){long long i,j,sum=0;cin>>n>>p>>tk>>wk>>tm>>wm;N=2*n;for(i=1;i<=n;i++)scanf("%I64d",&a[i]);for(i=1;i<=n;i++){add_edge(N+1,i,0,a[i]);add_edge(N+1,i+n,p,inf);if(i!=n)add_edge(i,i+1,0,inf);}for(i=1;i<=n;i++){if(i+tk<=n)add_edge(i,i+n+tk,wk,inf);if(i+tm<=n)add_edge(i,i+n+tm,wm,inf);add_edge(i+n,N+2,0,a[i]);}maxflow=0;    mincost=0;while(findpath())addflow();    printf("%I64d\n",mincost);}



0 0
原创粉丝点击