为什么昨天看的时候就一直看不懂,果然智商是硬伤。。。然后今晚一看就懂了OrzOrz,关键是限制容量那个技巧。。。
--------------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int inf=0x3f3f3f3f;
int read(){
int x=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c)){
x=x*10+c-‘0‘;
c=getchar();
}
return x;
}
struct edge{
int to,cap,cost;
edge *next,*rev;
};
edge e[20005],*pt=e,*cur[1005],*p[1005],*head[1005];
int d[1005],cnt[1005],inq[1005],a[1005];
void add(int u,int v,int d,int w){
pt->to=v;pt->cap=d;pt->cost=w;pt->next=head[u];head[u]=pt++;
}
void adde(int u,int v,int d,int w){
add(u,v,d,w);add(v,u,0,-w);
head[u]->rev=head[v];
head[v]->rev=head[u];
}
struct Edge{
int from,to,cap,cost;
}edges[5005];
int maxflow(int s,int t,int n){
clr(d,0);clr(cnt,0);cnt[0]=n;
int flow=0,a=inf,x=s;
while(d[s]<n){
edge *ee;
for(ee=cur[x];ee;ee=ee->next)
if(ee->cap>0&&d[ee->to]+1==d[x]) break;
if(ee){
p[ee->to]=cur[x]=ee;
a=min(a,ee->cap);
x=ee->to;
if(x==t){
while(x!=s){
p[x]->cap-=a;
p[x]->rev->cap+=a;
x=p[x]->rev->to;
}
flow+=a;
a=inf;
}
}else{
if(!--cnt[d[x]]) break;
d[x]=n;
for(ee=head[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]+1<d[x]){
d[x]=d[ee->to]+1;
cur[x]=ee;
}
}
cnt[d[x]]++;
if(x!=s) x=p[x]->rev->to;
}
}
return flow;
}
int mincost(int s,int t){
int cost=0;
while(1){
clr(d,inf);clr(inq,0);
d[s]=0;a[s]=inf;
queue<int>q;q.push(s);inq[s]=1;
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(edge *ee=head[x];ee;ee=ee->next){
if(ee->cap>0&&d[x]+ee->cost<d[ee->to]){
d[ee->to]=d[x]+ee->cost;
p[ee->to]=ee;
a[ee->to]=min(a[x],ee->cap);
if(!inq[ee->to]){
q.push(ee->to);inq[ee->to]=1;
}
}
}
}
if(d[t]==inf) break;
cost+=a[t]*d[t];
int x=t;
while(x!=s){
p[x]->cap-=a[t];
p[x]->rev->cap+=a[t];
x=p[x]->rev->to;
}
}
return cost;
}
int main(){
int n=read(),m=read(),k=read();
rep(i,m){
Edge &o=edges[i];
o.from=read(),o.to=read(),o.cap=read(),o.cost=read();
adde(o.from,o.to,o.cap,0);
}
int s=1,t=n;
printf("%d ",maxflow(s,t,n));
rep(i,m){
Edge &o=edges[i];
adde(o.from,o.to,inf,o.cost);
}
adde(0,s,k,0);adde(t,n+1,k,0);
printf("%d\n",mincost(0,n+1));
return 0;
}
--------------------------------------------------------------------------------------------
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 2262 Solved: 1129
[Submit][Status][Discuss]
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
Output
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
Sample Input
5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
Sample Output
13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10