题目
[ZJOI2010]网络扩容
(A:)报告,发现一道水题
(B:)切掉切掉
做法
考虑做第二问,(ufrac{~~f~~}{~~0~~}v,ufrac{~~K~~}{~~c~~}v),然后跑最大流最小费用就好了
My complete code
#include<bits/stdc++.h>
using namespace std;
typedef int LL;
const LL maxn=30009,inf=0x3f3f3f3f;
LL n,m,S,T,K,ans;
LL U[maxn],V[maxn],F[maxn],W[maxn];
struct E{
struct node{
LL to,next,f,c;
}dis[maxn];
LL num;
LL head[maxn],lev[maxn];
bool visit[maxn];
inline void Init(){
memset(head,-1,sizeof(head)), num=-1;
}
inline void Add(LL u,LL v,LL f,LL c=0){
dis[++num]=(node){v,head[u],f,c}, head[u]=num;
}
inline bool Bfs(){
queue<LL> que;
memset(lev,0,sizeof(lev)), memset(visit,false,sizeof(visit));
que.push(S); visit[S]=true; lev[S]=0;
while(que.size()){
LL u(que.front()); que.pop();
for(LL i=head[u];~i;i=dis[i].next){
LL v(dis[i].to);
if(!visit[v] && dis[i].f)
lev[v]=lev[u]+1,visit[v]=true,que.push(v);
}
}return lev[T];
}
LL Dfs(LL u,LL f){
if(u==T) return f;
LL tmp(f);
for(LL i=head[u];~i;i=dis[i].next){
LL v(dis[i].to),now;
if(dis[i].f &&lev[v]==lev[u]+1){
if(now=Dfs(v,min(tmp,dis[i].f))){
dis[i].f-=now, dis[i^1].f+=now;
tmp-=now;
if(!tmp) break;
}else lev[v]=-1;
}
}return f-tmp;
}
inline LL Dinic(){
LL ret(0);
while(Bfs()) ret+=Dfs(S,inf);
return ret;
}
LL pre_d[maxn],pre_v[maxn],cost[maxn],flow[maxn];
inline bool EK(){
memset(pre_d,0,sizeof(pre_d)), memset(pre_v,0,sizeof(pre_v)), memset(cost,inf,sizeof(cost));
memset(flow,0,sizeof(flow));
queue<LL> que;
que.push(S);
cost[S]=0, flow[S]=inf;
while(que.size()){
LL u(que.front()); que.pop();
for(LL i=head[u];~i;i=dis[i].next){
LL v(dis[i].to);
if(cost[v]>cost[u]+dis[i].c && dis[i].f){
flow[v]=min(flow[u],dis[i].f);
cost[v]=cost[u]+dis[i].c;
pre_d[v]=i, pre_v[v]=u;
que.push(v);
}
}
}return pre_v[T];
}
inline LL Solve(){
LL ret(0);
while(EK()){
ret+=flow[T]*cost[T];
for(LL i=T;i!=S;i=pre_v[i]){
dis[pre_d[i]].f-=flow[T],
dis[pre_d[i]^1].f+=flow[T];
}
}return ret;
}
}G1,G2;
int main(){
cin>>n>>m>>K;
G1.Init();
S=1, T=n;
for(LL i=1;i<=m;++i)
cin>>U[i]>>V[i]>>F[i]>>W[i],
G1.Add(U[i],V[i],F[i]), G1.Add(V[i],U[i],0);
ans=G1.Dinic();
printf("%d ",ans);
G2.Init();
S=n+1,T=n+2;
G2.Add(S,1,ans+K,0),G2.Add(1,S,0,0);
G2.Add(n,T,ans+K,0),G2.Add(T,n,0,0);
for(LL i=1;i<=m;++i){
G2.Add(U[i],V[i],F[i],0), G2.Add(V[i],U[i],0,0);
G2.Add(U[i],V[i],K,W[i]), G2.Add(V[i],U[i],0,-W[i]);
}
ans=G2.Solve();
printf("%d",ans);
return 0;
}