题目描述
给出一个包含 nn 个点和 mm 条边的有向图(下面称其为网络) G=(V,E)G=(V,E),该网络上所有点分别编号为 1 \sim n1∼n,所有边分别编号为 1\sim m1∼m,其中该网络的源点为 ss,汇点为 tt,网络上的每条边 (u,v)(u,v) 都有一个流量限制 w(u,v)w(u,v) 和单位流量的费用 c(u,v)c(u,v)。
你需要给每条边 (u,v)(u,v) 确定一个流量 f(u,v)f(u,v),要求:
- 0 \leq f(u,v) \leq w(u,v)0≤f(u,v)≤w(u,v)(每条边的流量不超过其流量限制);
- \forall p \in \{V \setminus \{s,t\}\}∀p∈{V∖{s,t}},\sum_{(i,p) \in E}f(i,p)=\sum_{(p,i)\in E}f(p,i)∑(i,p)∈Ef(i,p)=∑(p,i)∈Ef(p,i)(除了源点和汇点外,其他各点流入的流量和流出的流量相等);
- \sum_{(s,i)\in E}f(s,i)=\sum_{(i,t)\in E}f(i,t)∑(s,i)∈Ef(s,i)=∑(i,t)∈Ef(i,t)(源点流出的流量等于汇点流入的流量)。
定义网络 GG 的流量 F(G)=\sum_{(s,i)\in E}f(s,i)F(G)=∑(s,i)∈Ef(s,i),网络 GG 的费用 C(G)=\sum_{(i,j)\in E} f(i,j) \times c(i,j)C(G)=∑(i,j)∈Ef(i,j)×c(i,j)。
你需要求出该网络的最小费用最大流,即在 F(G)F(G) 最大的前提下,使 C(G)C(G) 最小。
输入格式
输入第一行包含四个整数 n,m,s,tn,m,s,t,分别代表该网络的点数 nn,网络的边数 mm,源点编号 ss,汇点编号 tt。
接下来 mm 行,每行四个整数 u_i,v_i,w_i,c_iui,vi,wi,ci,分别代表第 ii 条边的起点,终点,流量限制,单位流量费用。
输出格式
输出两个整数,分别为该网络的最大流 F(G)F(G),以及在 F(G)F(G) 最大的前提下,该网络的最小费用 C(G)C(G)。
输入输出样例
输入 #1复制
4 5 4 3 4 2 30 2 4 3 20 3 2 3 20 1 2 1 30 9 1 3 40 5
输出 #1复制
50 280
说明/提示
对于 100\%100% 的数据,1 \leq n \leq 5\times 10^31≤n≤5×103,1 \leq m \leq 5 \times 10^41≤m≤5×104,1 \leq s,t \leq n1≤s,t≤n,u_i \neq v_iui=vi,0 \leq w_i,c_i \leq 10^30≤wi,ci≤103,且该网络的最大流和最小费用 \leq 2^{31}-1≤231−1。
输入数据随机生成。
因为dijkstra不能求有负边的图,我们给每个边附上一个值,使得附上值后的所有边的权值均为正就能进行dijkstra了。(参照白皮书)
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
int n,m,source,sink;
int mincost,maxflow;
int head[(int)1e3*5+5];
int h[(int)1e3*5+5];
int dis[(int)1e3*5+5];
int prevv[(int)1e3*5+5];
int preve[(int)1e3*5+5];
struct node{
int to;
int w;
int nxt;
int dis;
}edge[(int)1e5+5];
int cnt;
void add_edge(int from,int to,int w,int dis)//w是容量
{
edge[cnt].to=to;
edge[cnt].w=w;
edge[cnt].dis=dis;
edge[cnt].nxt=head[from];
head[from]=cnt++;
}
bool dijkstra()
{
for(int i=0;i<=n;i++)dis[i]=INF;
priority_queue<P,vector<P>,greater<P> > que;
dis[source]=0;
que.push(P(0,source));
while(!que.empty())
{
P p=que.top();
que.pop();
int v=p.second;
if(p.first>dis[v])continue;
for(int i=head[v];~i;i=edge[i].nxt)
{
int to=edge[i].to,cost=edge[i].dis;
if(edge[i].w>0&&dis[to]>dis[v]+cost+h[v]-h[to])
{
dis[to]=dis[v]+cost+h[v]-h[to];
prevv[to]=v;
preve[to]=i;
que.push(P(dis[to],to));
}
}
}
if(dis[sink]==INF)return false;
return true;
}
void MCMF() {
while (dijkstra())
{
for(int i=1;i<=n;i++)h[i]+=dis[i];
int flow=INF;
for(int i=sink;i!=source;i=prevv[i])
{
flow=min(flow,edge[preve[i]].w);
}
mincost+=flow*h[sink];
maxflow+=flow;
for(int i=sink;i!=source;i=prevv[i])
{
edge[preve[i]].w-=flow;
edge[preve[i]^1].w+=flow;
}
}
//cout<<maxflow<<" "<<mincost;
printf("%ld %ld",maxflow,mincost);
}
signed main()
{
memset(head,-1,sizeof(head));
scanf("%ld%ld%ld%ld",&n,&m,&source,&sink);
int x,y,z,k;
for(int i=0;i<m;i++)
{
//cin>>x>>y>>z>>k;
scanf("%ld%ld%ld%ld",&x,&y,&z,&k);
add_edge(x,y,z,k);
add_edge(y,x,0,-k);
}
MCMF();
return 0;
}