传送门
【代码~】
为什么我的常数又这么大。。。。
第一问就是一裸的最大流,应该不用说了吧。。。。
第二问一开始我的想法是在残留网络上新建一个t->T容量为k费用为0的边然后跑费用流。。。。
然后。。。。
他死了。。。。(不过竟然有90pts真是服了)
因为跑最大流的时候很有可能把两点之间费用最小的那条路跑满,在残留网络中他就不会出现,所以咕咕。
所以直接重新建一次图,两点之间连两条边,一条容量为w费用为0表示原有的边,另一条容量为INF费用为w,表示扩容边。
然后在这个图上跑最小费用流就好了。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e4+10;
const int MAXM=2e5+10;
const int INF=0x3f3f3f3f;
int n,m,cnt,k,s,t,S,T,cost;
int xx[MAXM],yy[MAXM],zz[MAXM],ff[MAXM];
int head[MAXN],cur[MAXN],depth[MAXN],dis[MAXN],vis[MAXN],work[MAXN];
int nxt[MAXM],to[MAXM],w[MAXM],c[MAXM];
int w1[MAXM];
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void Add(int x,int y,int z,int f){
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=z;
c[cnt]=f;
cnt++;
}
void add(int x,int y,int z,int f){
Add(x,y,z,f);
Add(y,x,0,-f);
}
int bfs(){
queue<int> q;
memset(depth,0,sizeof(depth));
depth[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(!depth[v]&&w[i]){
depth[v]=depth[u]+1;
q.push(v);
if(v==t)
return 1;
}
}
}
return 0;
}
int dfs1(int u,int flow){
if(u==t)
return flow;
for(int &i=cur[u];i!=-1;i=nxt[i]){
int v=to[i];
if(depth[v]==depth[u]+1&&w[i]){
int di=dfs1(v,min(w[i],flow));
if(di){
w[i]-=di;
w[i^1]+=di;
return di;
}
}
}
return 0;
}
int dinic1(){
int ret=0;
while(bfs()){
memcpy(cur,head,sizeof(head));
while(int d=dfs1(s,INF))
ret+=d;
}
return ret;
}
int SPFA(){
memset(dis,INF,sizeof(dis));
memset(work,0,sizeof(work));
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(dis[v]>dis[u]+c[i]&&w[i]){
dis[v]=dis[u]+c[i];
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return dis[T]<INF;
}
int dfs2(int u,int flow){
if(u==T){
cost+=dis[u]*flow;
return flow;
}
work[u]=1;
for(int &i=cur[u];i!=-1;i=nxt[i]){
int v=to[i];
if(dis[v]==dis[u]+c[i]&&!work[v]&&w[i]){
int di=dfs2(v,min(flow,w[i]));
if(di){
w[i]-=di;
w[i^1]+=di;
return di;
}
}
}
return 0;
}
int dinic2(){
int ret=0;
while(SPFA()){
memcpy(cur,head,sizeof(head));
while(int d=dfs2(s,INF))
ret+=d;
}
return ret;
}
int main(){
memset(head,-1,sizeof(head));
n=Read(),m=Read(),k=Read();
s=1,t=n;
for(int i=1;i<=m;++i){
xx[i]=Read(),yy[i]=Read(),zz[i]=Read(),ff[i]=Read();
add(xx[i],yy[i],zz[i],0);
}
int x=dinic1();
cout<<x<<' ';
T=n+1;
memset(head,-1,sizeof(head));
cnt=0;
for(int i=1;i<=m;++i){
add(xx[i],yy[i],zz[i],0);
add(xx[i],yy[i],INF,ff[i]);
}
add(t,T,k+x,0);
dinic2();
cout<<cost<<'\n';
return 0;
}