记录编号 177813 评测结果 AAAAAAAAAA
题目名称 [ZJOI 2010] 网络扩容 最终得分 100
用户昵称 Gravatar真红之蝶 是否通过 通过
代码语言 C++ 运行时间 0.078 s
提交时间 2015-08-12 19:18:53 内存使用 3.19 MiB
显示代码纯文本
/*先求一遍最大流,解决第一问。
在残量网络中有两类边:
1.剩余流量为零的边将其容量设为无穷,费用设为单位费用。
2.剩余流量不为零的边将其拆为两条边,一条容量设为剩余容量,费用设为0,另一条容量设为无穷,费用设为单位费用。
因为增加k容量,所以新增一个0号点,边(0,1)容量为k,费用为0,同时添加反向边。
最后在新图中跑spfa即可*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,k,a,b,c,d,ans,ask,dis[1005],v[1005],first[1005],deep[1005],tot=1,que[250000],head=0,tail=-1,tat,pre[1005],minn=0x7fffffff;
int minc(int a,int b){return a<b?a:b;}
struct bian
{
    int from,to,ex_fare,flow_fare,next; 
}s[100000];
void add(int a,int b,int c,int d)
{
    s[++tot].from=a;
    s[tot].to=b;
    s[tot].flow_fare=c;
    s[tot].ex_fare=d;
    s[tot].next=first[a];
    first[a]=tot;
    s[++tot].from=b;
    s[tot].to=a;
    s[tot].flow_fare=0;
    s[tot].ex_fare=-d;
    s[tot].next=first[b];
    first[b]=tot;
}
struct data
{
    int q,jvli;
    friend bool operator < (data a,data b)
    {
        return a.jvli>b.jvli;
    }
}cc,cd;
priority_queue<data>q;
int spfa(int x)
{
    memset(dis,63,sizeof(dis));
    memset(v,false,sizeof(v));
    dis[x]=0;
    cc.q=x;
    cc.jvli=0;
    v[x]=1;
    q.push(cc);
    while(!q.empty())
    {
        cd=q.top();
        v[cd.q]=0;
        q.pop();
        for(int i=first[cd.q];i!=-1;i=s[i].next)
        {
            int u=s[i].to;
            if(s[i].flow_fare>0&&dis[u]>dis[cd.q]+s[i].ex_fare)
            {
                dis[u]=dis[cd.q]+s[i].ex_fare;
                pre[u]=i;
                if(!v[u])
                {
                    v[u]=1;
                    cc.q=u;
                    cc.jvli=dis[u];
                    q.push(cc);
                }
            }
        }
    }
    if(dis[n]<100000000)
        return 1;
    else
        return 0;
}
int dfs(int x,int now_fare)
{
    if(x==n)
        return now_fare;
    int rest_fare=0;
    for(int i=first[x];i!=-1;i=s[i].next)
    {
        int j=s[i].to;
        if(s[i].flow_fare>0&&deep[j]==deep[x]+1&&(rest_fare=dfs(j,minc(s[i].flow_fare,now_fare))))
        {
            s[i].flow_fare-=rest_fare;
            s[i^1].flow_fare+=rest_fare;
            return rest_fare;
        }
    }
    return 0;
}
int bfs()
{
    head=0,tail=-1;
    for(int i=1;i<=n;++i) 
        deep[i]=-1;
    deep[1]=1,que[++tail]=1;
    while(head<=tail)
    {
        int u=que[head++];
        for(int i=first[u];i!=-1;i=s[i].next)
        {
            int j=s[i].to;
            if(s[i].flow_fare>0&&deep[j]==-1)
            {
                deep[j]=deep[u]+1;
                que[++tail]=j;
            }
        }
    }
    //printf("%d\n",deep[n]);
    if(deep[n]>0)
        return 1;
    else
        return 0;
}
void dinic()
{
    ans=0;int ts=0;
    while(bfs())
    {
        if(ts=dfs(1,0x7fffffff))
            ans+=ts;
    }
    printf("%d ",ans);
}
void rebuild()
{
    tat=tot;
    s[++tat].from=0;
    s[tat].to=1;
    s[tat].flow_fare=k;
    s[tat].ex_fare=0;
    s[tat].next=first[0];
    first[0]=tat;
    s[++tat].from=1;
    s[tat].to=0;
    s[tat].flow_fare=0;
    s[tat].ex_fare=0;
    s[tat].next=first[1];
    first[1]=tat;
    for(int i=2;i<=tot;++i)
    {
        if((i&1)!=1)
        {
            s[++tat].flow_fare=0x7fffffff;
            s[tat].ex_fare=s[i].ex_fare;
            s[tat].from=s[i].from;
            s[tat].to=s[i].to;
            s[tat].next=first[s[i].from];
            first[s[i].from]=tat;
        }
        else
        {
            s[++tat].flow_fare=0;
            s[tat].ex_fare=-s[i].ex_fare;
            s[tat].from=s[i].from;
            s[tat].to=s[i].to;
            s[tat].next=first[s[i].from];
            first[s[i].from]=tat;
        }
        s[i].ex_fare=0;
    }
}
void min_fareflow()
{
    minn=0x7fffffff;
    for(int i=pre[n];i;i=pre[s[i].from])
        minn=minc(minn,s[i].flow_fare);
    //printf("%d\n",minn);
    for(int i=pre[n];i;i=pre[s[i].from])
    {
        s[i].flow_fare-=minn;
        s[i^1].flow_fare+=minn;
        ask+=minn*s[i].ex_fare;
    }
}
int main()
{
    freopen("networkzj2010.in","r",stdin);
    freopen("networkzj2010.out","w",stdout);
    memset(first,-1,sizeof(first));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        add(a,b,c,d);
    }
    dinic();
    rebuild();
    //for(int i=1;i<=tat;++i)
        //printf("%d %d %d %d %d\n",s[i].from,s[i].to,s[i].next,s[i].flow_fare,s[i].ex_fare);
    while(spfa(0))
        min_fareflow();
    printf("%d",ask);
    getchar();getchar();getchar();getchar();
    return 0;
}