题解:

拆点费用流

然后输出cost、flow

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100005;
int fi[N],n,t,cas,m,x,y,z,f[N],ne[N],num,zz[N],fl[N],gp[N],dist[N],pre[N],sl[N];
void jb(int x,int y,int z,int s)
{
    ne[num]=fi[x];
    fi[x]=num;
    zz[num]=y;
    sl[num]=z;
    fl[num++]=s;
    ne[num]=fi[y];
    fi[y]=num;
    zz[num]=x;
    sl[num]=0;
    fl[num++]=-s;
}
int spfa()
{
    memset(dist,0x3f,sizeof dist);
    memset(pre,-1,sizeof pre);
    memset(gp,0,sizeof gp);
    memset(f,0,sizeof f);
    queue<int > Q;
    Q.push(1);
    dist[1]=0;
    while (!Q.empty())
     {
         int now=Q.front();
         Q.pop();
         f[now]=0;
         for (int i=fi[now];i!=-1;i=ne[i])
          if (sl[i]>0)
           {
              int t=zz[i];
              if (dist[t]>dist[now]+fl[i])
               {
                   dist[t]=dist[now]+fl[i];
                   pre[t]=now;
                   gp[t]=i;
                   if (!f[t])
                    {
                        f[t]=1;
                        Q.push(t);
                    }
               }
           }
     }
    if (pre[n]==-1)return 1;
    return 0; 
}
void Max_flow()
{
    int cost=0,flow=0;
    while (!spfa())
     {
         int f=1e9;
         for (int i=n;i>1;i=pre[i])
          f=min(f,sl[gp[i]]);
         cost+=f;
        flow+=dist[n]*f;
        for (int i=n;i>1;i=pre[i])
         {
             sl[gp[i]]-=f;
             sl[gp[i]^1]+=f;
         } 
     }
    printf("%d %d\n",cost,flow);
}
int main()
{
    memset(fi,-1,sizeof fi);
    scanf("%d%d",&n,&m);
    while (m--)
     {
         scanf("%d%d%d",&x,&y,&z);
         jb(x+n,y,1,z); 
     }
    for (int i=2;i<n;i++)jb(i,i+n,1,0);
    jb(1,1+n,1e9,0);
    jb(n,n+n,1e9,0);
    n=n+n;
    Max_flow();
}

 

posted on 2018-02-02 09:33  宣毅鸣  阅读(123)  评论(0编辑  收藏  举报