题面:
分析:
第一问就是裸的dinic, 第二问 需要有点想法, 最大流增加K所需的最小扩容费用, 先想下怎样能增加,再想下怎么限制增加K?
deal:
怎样增加 就是对于整个图 加边 容量为 INF 花费为之前的花费,限制增加 K的话,我们只要 建一个源点->1 容量为 K
费用流模板题
#include<bits/stdc++.h>
#define ks ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define fr first
#define sc second
#define pb push_back
#define pf push_front
#define mp make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pa;
typedef set<int>::iterator sit;
typedef multiset<int>::iterator msit;
template<class T>inline void read(T &res){
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
void wenjian(){freopen("concatenation.in","r",stdin);freopen("concatenation.out","w",stdout);}
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct chongzai{int c; bool operator<(const chongzai &b )const{ return c>b.c; } }sss;
const int maxn=1e6+177;
const int maxm=1e6+177;
const ll mod=0x3f3f3f3f3f3f3f3f;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int s,t; // 源点 汇点
int n,m,k;
ll dis[maxn],incf[maxn],maxflow,ans;
int vis[maxn];
int pre[maxn];
struct Node{
int next;
int to;
ll vul;
ll cost;
}edge[maxm];
int head[maxn];
int tot;
void add(int from,int to,ll vul,ll cost){
edge[++tot].next=head[from];
edge[tot].to=to;
edge[tot].vul=vul;
edge[tot].cost=cost;
head[from]=tot;
edge[++tot].next=head[to];
edge[tot].to=from;
edge[tot].vul=0;
edge[tot].cost=-cost;
head[to]=tot;
}
bool spfa(){
queue<int >qu;
for(int i=0;i<n*2;i++){
dis[i]=INF;
vis[i]=0;
}
qu.push(s);
dis[s]=0;
vis[s]=1;
incf[s]=INF;
pre[t]=-1;
while(qu.size()){
int x=qu.front();
vis[x]=0;
qu.pop();
for(int i=head[x];i;i=edge[i].next){
if(!edge[i].vul){
continue;
}
int y=edge[i].to;
if(dis[y]>dis[x]+edge[i].cost){
dis[y]=dis[x]+edge[i].cost;
incf[y]=min(incf[x],edge[i].vul);
pre[y]=i;
if(!vis[y]){
vis[y]=1;
qu.push(y);
}
}
}
}
// printf("@@@ %lld %d %d\n",dis[t],t,pre[t]);
if(pre[t]==-1){
// printf("*& \n");
return false;
}
return true;
}
void update(){
int x=t;
while(x!=s){
int i=pre[x];
edge[i].vul-=incf[t];
edge[i^1].vul+=incf[t];
x=edge[i^1].to;
}
maxflow+=incf[t];
ans+=dis[t]*incf[t];
}
bool bfs(){
memset(dis,0,sizeof(dis));
queue<int >qu;
qu.push(s);
dis[s]=1;
while(qu.size()){
int x=qu.front();
qu.pop();
for(int i=head[x];i;i=edge[i].next){
if(edge[i].vul&&!dis[edge[i].to]){
qu.push(edge[i].to);
dis[edge[i].to]=dis[x]+1;
if(edge[i].to==t){
return true;
}
}
}
}
return false;
}
ll dinic(int x,ll flow){
if(x==t){
return flow;
}
ll rest=flow,k;
for(int i=head[x];i&&rest;i=edge[i].next){
if(edge[i].vul&&dis[edge[i].to]==dis[x]+1){
k=dinic(edge[i].to,min(rest,edge[i].vul));
if(!k){
dis[edge[i].to]=0;
}
edge[i].vul-=k;
edge[i^1].vul+=k;
rest-=k;
}
}
return flow-rest;
}
void deal1(){ // 最大流
ll flow=0,maxflow1=0;
while(bfs()){
while(flow=dinic(s,INF)){
maxflow1+=flow;
}
}
printf("%lld ",maxflow1);
}
void deal2(){ // 费用流
ans=0;
while(spfa()){
update();
}
printf("%lld\n",ans);
}
void init(){
tot=1;
memset(head,0,sizeof(head));
}
int u[maxm],v[maxm];
ll w[maxm];
int main(){
init();
scanf("%d%d%d",&n,&m,&k);
s=1;t=n;
int c;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&u[i],&v[i],&c,&w[i]);
add(u[i],v[i],c,0);
}
deal1();
for(int i=1;i<=m;i++){
add(u[i],v[i],INF,w[i]);
}
s=n+1;
add(s,1,k,0);
deal2();
return 0;
}