BZOJ[1877]晨跑 费用流

来源:互联网 发布:主要的网络侦查技术有 编辑:程序博客网 时间:2024/06/14 08:13

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=1877

题目大意:给一有向图G,多次从1到n,最大化经过点数,最小化边权和

把每个点拆成入和出,将除1,n的所有点入向出连一条容量为1,费用为0的边
1和n的连INF(不限制经过次数)
超级源连1的入,n的出连汇,容量都是INF,费用为0
对于每条边(u,v,k),从u的出到v的入连一条容量为1费用为k的边

跑最小费用最大流

代码如下:

#include<ctype.h>#include<cstdio>#include<queue>#define N 505#define INF 2147483647using namespace std;const int S=501;const int T=502;queue<int>q;int n,m,x,y,k,ans,cost,top=1;int d[N],fir[N];bool b[N];inline int read(){    int x=0,f=1;char c;    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));    return x*f;}struct Edge{    int to,nex,k,v;    Edge(int _=0,int __=0,int ___=0,int ____=0):to(_),nex(__),k(___),v(____){}}nex[40020];inline void add(int x,int y,int k,int v){    nex[++top]=Edge(y,fir[x],k,v);    fir[x]=top;}inline bool spfa(){    for(int i=1;i<=502;i++) d[i]=INF,b[i]=false;    d[S]=0;q.push(S);    while(!q.empty()){        int x=q.front();q.pop();        b[x]=false;        for(int i=fir[x];i;i=nex[i].nex)            if(nex[i].k && d[nex[i].to]>d[x]+nex[i].v){                d[nex[i].to]=d[x]+nex[i].v;                if(!b[nex[i].to]) q.push(nex[i].to),b[nex[i].to]=true;            }    }    return d[T]!=INF;}int dfs(int x,int v){    if(!v || x==T){        cost+=v*d[T];        return v;    }    int tmp=0;    b[x]=true;    for(int i=fir[x];i;i=nex[i].nex)        if(!b[nex[i].to] && nex[i].k && d[nex[i].to]==d[x]+nex[i].v){            int f=dfs(nex[i].to,min(v,nex[i].k));            v-=f;nex[i].k-=f;nex[i^1].k+=f;tmp+=f;            if(!v) break;        }    if(!tmp) d[x]=-1;    return tmp;}inline void Dinic(){    while(spfa()) ans+=dfs(S,INF);}int main(){    n=read();m=read();    for(int i=2;i<n;i++) add(i,i+n,1,0),add(i+n,i,0,0);    for(int i=1;i<=m;i++){        x=read();y=read();k=read();        add(x+n,y,1,k);add(y,x+n,0,-k);    }    add(1,1+n,INF,0);add(1+n,1,0,0);add(n,n+n,INF,0);add(n+n,n,0,0);    add(S,1,INF,0);add(1,S,0,0);add(n+n,T,INF,0);add(T,n+n,0,0);    Dinic();    printf("%d %d",ans,cost);return 0;}
原创粉丝点击