bzoj1834: [ZJOI2010]network 网络扩容 费用流

bzoj1834
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求:
1、在不扩容的情况下,1到N的最大流;
2、将1到N的最大流增加K所需的最小扩容费用。
Input
第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
N<=1000,M<=5000,K<=10
Output
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
先按每条费用为0,容量为c跑费用流求最大流量,然后对原图中每条边建一条容量inf,费用为w的边,新建超级源和1连边,容量k,费用0,
因为要保证流量增加k,而且原图中的边是没有费用的,而只要增加 了费用,流量一定够,所以设成inf

/**************************************************************
    Problem: 1834
    User: walfy
    Language: C++
    Result: Accepted
    Time:112 ms
    Memory:2720 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double eps=1e-6;
const int N=20000+10,maxn=50000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
struct edge{
    int to,Next,c;
    int cost;
}e[maxn];
int cnt,head[N];
int s,t;
int dis[N],pre[N],path[N];
bool vis[N];
void add(int u,int v,int c,int cost)
{
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].cost=cost;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].cost=-cost;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
bool spfa()
{
    memset(pre,-1,sizeof pre);
    memset(dis,inf,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[s]=0;
    vis[s]=1;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(e[i].c>0&&dis[x]+e[i].cost<dis[te])
            {
                dis[te]=dis[x]+e[i].cost;
                pre[te]=x;
                path[te]=i;
                if(!vis[te])q.push(te),vis[te]=1;
            }
        }
    }
    return pre[t]!=-1;
}
int maxflow()
{
    int flow=0;
    while(spfa())
    {
        int f=inf;
        for(int i=t;i!=s;i=pre[i])
            if(e[path[i]].c<f)
               f=e[path[i]].c;
        flow+=f;
        for(int i=t;i!=s;i=pre[i])
        {
            e[path[i]].c-=f;
            e[path[i]^1].c+=f;
        }
    }
    return flow;
}
int mincostmaxflow()
{
    int cost=0,flow=0;
    while(spfa())
    {
        int f=inf;
        for(int i=t;i!=s;i=pre[i])
            if(e[path[i]].c<f)
               f=e[path[i]].c;
        flow+=f;
        cost+=dis[t]*f;
        for(int i=t;i!=s;i=pre[i])
        {
            e[path[i]].c-=f;
            e[path[i]^1].c+=f;
        }
    }
    return cost;
}
void init()
{
    memset(head,-1,sizeof head);
    cnt=0;
}
struct node{int u,v,c,w;}te[N];
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    init();
    for(int i=0;i<m;i++)
    {
        int u,v,c,w;
        scanf("%d%d%d%d",&u,&v,&c,&w);
        add(u,v,c,0);
        te[i]={u,v,c,w};
    }
    s=1,t=n;
    printf("%d ",maxflow());
    for(int i=0;i<m;i++)
        add(te[i].u,te[i].v,inf,te[i].w);
    s=n+1;add(s,1,k,0);
    printf("%d\n",mincostmaxflow());
    return 0;
}
/********************
 
********************/
posted @ 2018-07-12 21:57  walfy  阅读(180)  评论(0编辑  收藏  举报