BZOJ 1877

来源:互联网 发布:api原油库存数据官网 编辑:程序博客网 时间:2024/05/17 12:05

这题是最小费用最大流。
拆一下点即可,每个点拆成出点和入点。然后跑一边最小费用最大流,分别输出最大流和最小费用即可。


代码如下,啊,好慢→→

/**************************************************************    Problem: 1877    User: fantasticwtl    Language: C++    Result: Accepted    Time:908 ms    Memory:1724 kb****************************************************************/#include <cstdio>#include <memory.h>using namespace std;int ans,ss,n,m,x,y,z,w[405][405],d[10001],q[10001],pr[10001];bool ff[405],f[405][405];bool spfa (){    memset(ff,0,sizeof(ff));memset(pr,0,sizeof(pr));memset(d,60,sizeof(d));    ff[n+1]=1;q[1]=n+1;int h=0,t=1;d[n+1]=0;    while(h<t){        h++;        for(int i=1;i<=2*n;i++)         if(f[q[h]][i]&&d[i]>d[q[h]]+w[q[h]][i]){             d[i]=d[q[h]]+w[q[h]][i];             pr[i]=q[h];             if(!ff[i])q[++t]=i,ff[i]=1;         }         ff[q[h]]=0;    }    if(d[n]>1000000)return 0;    ans+=d[n];    return 1;}int main (){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),f[n+x][y]=1,w[n+x][y]+=z,w[y][n+x]-=z;//输入部分    for(int i=1;i<=n;i++)f[i][i+n]=1;//出点与入点连边    while(spfa ()){//最小费用最大流        int k=n;ss++;        while(k!=n+1)f[pr[k]][k]=0,f[k][pr[k]]=1,k=pr[k];    }    printf("%d %d\n",ss,ans);}
1 0
原创粉丝点击