题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入格式
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
输出格式
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。
输入输出样例
输入 #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
#include<bits/stdc++.h>
const int maxn = 5e4 + 10;
int head[maxn];
int vis[maxn];
int dis[maxn];
int flow[maxn];
int pre[maxn];
int last[maxn];
int tot;
int n, m, s, t;
using namespace std;
struct node{
int to;
int next;
int f;
int w;
node() {}
node(int a, int b, int c, int d) : to(a), next(b), f(c), w(d) {}
}edge[maxn * 10];
void edgeadd(int a, int b, int c, int d){
edge[tot] = node(b, head[a], c, d);
head[a] = tot++;
edge[tot] = node(a, head[b], 0, -d);
head[b] = tot++;
}
void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
void spfainit(){
memset(vis, 0, sizeof(vis));
memset(dis, 0X3f3f, sizeof(dis));
memset(flow, 0x3f3f, sizeof(flow));
}
bool spfa(){
spfainit();
queue<int> q;
q.push(s);
pre[t] = -1;
vis[s] = 1;
dis[s] = 0;
//flow[s] = 0;
while(!q.empty()){
int nw = q.front();
q.pop();
vis[nw] = 0;
for(int i = head[nw]; i != -1; i = edge[i].next){
int y = edge[i].to;
int w = edge[i].w;
int f = edge[i].f;
if(f && dis[y] > dis[nw] + w){
dis[y] = dis[nw] + w;
flow[y] = min(flow[nw], f);
pre[y] = nw;
last[y] = i;
if(!vis[y]){
q.push(y);
vis[y] = 1;
}
}
}
}
return pre[t] != -1;
}
void dinic(){
int maxflow = 0, minw = 0;
while(spfa()){
maxflow += flow[t];
minw += flow[t] * dis[t];
int x = t;
while(x != s){
edge[last[x]].f -= flow[t];
edge[(last[x] ^ 1)].f += flow[t];
x = pre[x];
}
}
cout << maxflow << " " << minw << endl;
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m >> s >> t;
init();
for(int i = 1; i <= m; i++){
int a, b, c, d;
cin >> a >> b >> c >> d;
edgeadd(a, b, c, d);
}
dinic();
return 0;
}