洛谷 P2604 [ZJOI2010]网络扩容

题目描述

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

输入输出格式

输入格式:

输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

输出格式:

输出文件一行包含两个整数,分别表示问题1和问题2的答案。

输入输出样例

输入样例#1:

5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1

输出样例#1:

13 19

说明

30%的数据中,N<=100

100%的数据中,N<=1000,M<=5000,K<=10

第一问 任何费用为0,流量为给定流量的最大流

第二问 源点到第一个点流量为k 其他流量为inf ,费用为给定费用的费用流

屠龙宝刀点击就送

#include <cstring>
#include <ctype.h>
#include <cstdio>
#include <queue>
#define M 50005
#define inf 0x7fffffff

using namespace std;
void read(int &x)
{
    x=0;bool f=0;
    register char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘;
    x=f?(~x)+1:x;
}
struct Edge
{
    int next,to,flow,value;
    Edge(int next=0,int to=0,int flow=0,int value=0) :next(next),to(to),flow(flow),value(value) {}
}edge[M<<1];
bool vis[M<<1];
int u[M],v[M],c[M],w[M],n,m,k,dep[M<<1],dis[M<<1],fa[M<<1],flow[M<<1],head[M<<1],cnt=1;
void insert(int u,int v,int w,int l)
{
    edge[++cnt]=Edge(head[u],v,w,l);
    head[u]=cnt;
}
bool bfs(int s,int t)
{
    memset(dep,-1,sizeof(dep));
    dep[s]=0;
    queue<int>Q;
    Q.push(s);
    while(!Q.empty())
    {
        int now=Q.front();
        Q.pop();
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]==-1&&edge[i].flow>0)
            {
                dep[v]=dep[now]+1;
                if(v==t) return true;
                Q.push(v);
            }
        }
    }
    return false;
}
int min(int a,int b) {return a>b?b:a;}
int dfs(int now,int t,int came_flow)
{
    if(now==t||came_flow==0) return came_flow;
    int f,res=0;
    for(int i=head[now];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(dep[v]==dep[now]+1&&edge[i].flow>0&&(f=dfs(v,t,min(came_flow,edge[i].flow))))
        {
            res+=f;
            came_flow-=f;
            edge[i].flow-=f;
            edge[i^1].flow+=f;
            if(came_flow==0) break;
        }
    }
    if(res!=came_flow) dep[now]=-1;
    return res;
}
bool spfa(int s,int t)
{
    for(int i=s;i<=t;i++) {flow[i]=inf;dis[i]=inf;vis[i]=0;}
    vis[s]=1;
    fa[s]=0;
    dis[s]=0;
    queue<int>Q;
    Q.push(s);
    while(!Q.empty())
    {
        int now=Q.front();
        Q.pop();
        vis[now]=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>dis[now]+edge[i].value&&edge[i].flow>0)
            {
                dis[v]=dis[now]+edge[i].value;
                flow[v]=min(flow[now],edge[i].flow);
                fa[v]=i;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    return dis[t]<inf;
}
int update(int s,int t)
{
    int x=flow[t];
    for(int i=t;i!=s&&i;i=edge[fa[i]^1].to)
    {
        edge[fa[i]].flow-=x;
        edge[fa[i]^1].flow+=x;
    }
    return dis[t]*x;
}
int dinic(int s,int t,int type)
{
    int ans=0;
    if(type==1)
        for(;bfs(s,t);ans+=dfs(s,t,inf));
    else for(;spfa(s,t);ans+=update(s,t));
    return ans;
}
int main()
{
    read(n);
    read(m);
    read(k);
    for(int i=1;i<=m;i++)
    {
        read(u[i]);
        read(v[i]);
        read(c[i]);
        read(w[i]);
        insert(u[i],v[i],c[i],0);
        insert(v[i],u[i],0,0);
    }
    printf("%d ",dinic(1,n,1));
    for(int i=1;i<=m;i++)
    {
        insert(u[i],v[i],inf,w[i]);
        insert(v[i],u[i],0,-w[i]);
    }
    insert(0,1,k,0);
    insert(1,0,0,0);
    printf("%d\n",dinic(0,n,2));
    return 0;
}
时间: 2024-07-30 20:30:37

洛谷 P2604 [ZJOI2010]网络扩容的相关文章

luogu P2604 [ZJOI2010]网络扩容 |费用流

题目描述 给定一张有向图,每条边都有一个容量\(C\)和一个扩容费用\(W\).这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入格式 输入文件的第一行包含三个整数\(N,M,K\),表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数\(u,v,C,W\),表示一条从u到v,容量为C,扩容费用为W的边. 输出格式 输出文件一行包含两个整数,分别表示问题1和问题2的答案. 利用残余网

p2604 [ZJOI2010]网络扩容

传送门 分析 第一问就是最大流 第二问用一个源点向1连一条流量为第一问答案+k的边然后跑费用流即可 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<

[zjoi2010]网络扩容

描述 Description  给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入格式 Input Format 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边. 输出格式 Output Format 输出文件一行包含两个整数

洛谷 P2038 无线网络发射器选址(NOIp2014D2T1)

题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻的平行街道之间的距离都是恒定值 1 .东西向街道从北到南依次编号为0,1,2-128 , 南北向街道从西到东依次编号为0,1,2-128 . 东西向街道和南北向街道相交形成路口,规定编号为x 的南北向街道和编号为y 的东西向街道形成的路口的坐标是(x , y ). 在 某 些 路口存在一定数量的公共

洛谷 P1546 最短网络 Agri-Net Label:Water最小生成树

题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场.为了用最小的消费,他想铺设最短的光纤去连接所有的农场. 你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案.每两个农场间的距离不会超过100000 输入输出格式 输入格式: 第一行: 农场的个数,N(3<=N<=100). 第二行..结尾: 后来的行包含了一

洛谷P1546 最短网络 Agri-Net

P1546 最短网络 Agri-Net 526通过 959提交 题目提供者JOHNKRAM 标签图论贪心USACO 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 50分C++代码,求解 请指教哪里出现了问题,只有… 求解为什么只有40分 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场.为了用最小的消费,他想铺设最短的光纤去连接所

洛谷 P1546 最短网络 Agri-Net x

题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场.为了用最小的消费,他想铺设最短的光纤去连接所有的农场. 你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案.每两个农场间的距离不会超过100000 输入输出格式 输入格式: 第一行: 农场的个数,N(3<=N<=100). 第二行..结尾: 后来的行包含了一

洛谷2038 无线网络发射器选址

题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网.假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻的平行街道之间的距离都是恒定值 1 .东西向街道从北到南依次编号为0,1,2…128 , 南北向街道从西到东依次编号为0,1,2…128 . 东西向街道和南北向街道相交形成路口,规定编号为x 的南北向街道和编号为y 的东西向街道形成的路口的坐标是(x ,  y ). 在 某 些 路口存在一定数量的公共

洛谷 P2038 无线网络发射器选址

P2038 无线网络发射器选址 注意边界是否小于0 1 #include<bits/stdc++.h> 2 using namespace std; 3 int d,n,num[1000][1000],ans[1000][1000],tot,cnt,maxx; 4 int main() 5 { 6 scanf("%d",&d); 7 scanf("%d",&n); 8 memset(num,0,sizeof(num)); 9 memset