函数功能介绍:
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);
}