由于题解已经烂大街了,这里只列出注意事项和部分个人难以理解的内容。
注意事项
- 边下标从2开始
- 区分流量和单价
- 使用dijkstra最好开long long 小心h[x]爆掉
h[x]+=dis[x]的正确性证明
代码库
SPFA
#include <cstdio>
#include <queue>
#include <algorithm>
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
#define Rep(i,a,b) for(REG int i=a;i>=b;i--)
inline char getc(){
static char buf[1<<14],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline int scan(){
REG int x=0; REG char ch=0;
while(ch<48) ch=getc();
while(ch>=48) x=x*10+ch-48,ch=getc();
return x;
}
const int N=5e3+5,M=5e4+5,INF=2147483647;
int n,m,s,t,head[N],nex[M<<1],to[M<<1],wei[M<<1],cost[M<<1];
inline void addEdge(int u,int v,int w,int c){
static int cc=1; //差点又忘了
nex[++cc]=head[u]; head[u]=cc;
to[cc]=v; wei[cc]=w; cost[cc]=c;
}
int h[N],dis[N],pre[N],prE[N];
bool vis[N]; std::queue<int> Q;
inline bool SPFA(){
//static int err=0;
//err++; if(err>10) return 0;
rep(i,1,n) dis[i]=INF,vis[i]=pre[i]=prE[i]=0;
Q.push(s); dis[s]=0; vis[s]=1;
//printf("order:
");
while(!Q.empty()){
REG int u=Q.front(); Q.pop(); vis[u]=0;
if(u==t) continue;
//到t就行了 注意这里不能break 因为只是搜到了t不代表dis[t]已经最小
for(REG int i=head[u];i;i=nex[i]){
if(!wei[i]) continue;
//printf("%d->%d %d cmp %d
",u,to[i],dis[u]+cost[i],dis[to[i]]);
//一条增广路的流量是相同的 所以求出的单位价格之和最小即可
if(dis[u]+cost[i]<dis[to[i]]){
dis[to[i]]=dis[u]+cost[i];
pre[to[i]]=u; prE[to[i]]=i;
if(!vis[to[i]]) vis[to[i]]=1,Q.push(to[i]);
}
}
}
//putchar('
');
return pre[t];
}
int Mflow,Mcost;
inline void calc(){
REG int u,flow;
for(u=t,flow=INF;pre[u];u=pre[u]) flow=std::min(flow,wei[prE[u]]);
Mflow+=flow; Mcost+=dis[t]*flow;
for(u=t;pre[u];u=pre[u]) wei[prE[u]]-=flow,wei[prE[u]^1]+=flow;
//printf("ss
");
}
int main(){
//freopen("P3381_8.in","r",stdin);
n=scan(),m=scan(),s=scan(),t=scan();
REG int u,v,w,c;
while(m--){
u=scan(),v=scan(),w=scan(),c=scan();
addEdge(u,v,w,c); addEdge(v,u,0,-c);
}
while(SPFA()) calc();
printf("%d %d
",Mflow,Mcost);
return 0;
}
dijkstra
#include <cstdio>
typedef long long ll;
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
#define Rep(i,a,b) for(REG int i=a;i>=b;i--)
inline char getc(){
static char buf[1<<14],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline int scan(){
REG int x=0; REG char ch=0;
while(ch<48) ch=getc();
while(ch>=48) x=x*10+ch-48,ch=getc();
return x;
}
inline ll min(const ll&a,const ll&b){ return a<b?a:b; }
template<typename T> inline void swap(T &a,T &b){ REG T t=a; a=b; b=t; }
const int N=5e3+5,M=5e4+5; const ll INF=1e18;
struct Heap{
struct node{
int i,siz; ll d; node *ch[2];
node(int a=0,ll b=0):i(a),d(b),siz(1){ ch[0]=ch[1]=NULL; }
inline void maintain(){
siz=1;
if(ch[0]) siz+=ch[0]->siz;
if(ch[1]) siz+=ch[1]->siz;
}
}*root;
inline void get_top(int &a,ll &b){ a=root->i; b=root->d; }
inline int _siz(const node *u){ return u?u->siz:0; }
inline ll _dis(const node *u){ return u?u->d:INF; }
inline void _insert(node*&u,int i,ll d){
if(!u) u=new node(i,d);
else{
if(u->d>d) swap(u->d,d),swap(u->i,i);
REG int judge=_siz(u->ch[0])-_siz(u->ch[1]);
_insert(u->ch[judge>0?1:0],i,d);
u->maintain();
}
}
inline void _delete(node*&u){
if(u->ch[0]||u->ch[1]){
REG int j=_dis(u->ch[0])-_dis(u->ch[1])>0?1:0;
swap(u->d,u->ch[j]->d); swap(u->i,u->ch[j]->i);
_delete(u->ch[j]); u->maintain();
}else{ delete u; u=NULL; }
}
}Q;
int n,s,t,head[N],nex[M<<1],to[M<<1]; ll wei[M<<1],cost[M<<1];
inline void addEdge(int u,int v,int w,int c){
static int cc=1;
nex[++cc]=head[u]; head[u]=cc;
to[cc]=v; wei[cc]=w; cost[cc]=c;
}
ll h[N],dis[N],Mcost,Mflow; int pre[N],preE[N]; bool vis[N];
inline bool dijkstra(){
//static int cnt=0;
//if((++cnt)&&Mflow>2938) return printf("%d
",cnt),0;
rep(i,1,n) dis[i]=INF,pre[i]=preE[i]=vis[i]=0;
Q._insert(Q.root,s,0); dis[s]=0;
while(Q.root){
REG int u; REG ll d;
Q.get_top(u,d); Q._delete(Q.root);
if(d>dis[u]||vis[u]||u==t) continue;
vis[u]=1;
for(REG int i=head[u];i;i=nex[i]){
if(!wei[i]||vis[to[i]]) continue;
REG ll eff=cost[i]+h[u]-h[to[i]];
if(dis[u]+eff<dis[to[i]]){
dis[to[i]]=dis[u]+eff;
pre[to[i]]=u; preE[to[i]]=i;
Q._insert(Q.root,to[i],dis[to[i]]);
}
}
}
return pre[t];
}
inline void calc(){
REG ll per_cost=dis[t]-h[s]+h[t],flow=INF;
//注意这里的wei[...]
for(REG int i=t;pre[i];i=pre[i]) flow=min(flow,wei[preE[i]]);
Mflow+=flow; Mcost+=flow*per_cost;
for(REG int i=t;pre[i];i=pre[i]) wei[preE[i]]-=flow,wei[preE[i]^1]+=flow;
rep(i,1,n) h[i]+=dis[i];
}
int main(){
//freopen("P3381_8.in","r",stdin);
REG int m,u,v,w,c;
n=scan(),m=scan(),s=scan(),t=scan();
while(m--){
u=scan(),v=scan(),w=scan(),c=scan();
addEdge(u,v,w,c); addEdge(v,u,0,-c);
}
//printf("ss");
while(dijkstra()) calc();
printf("%lld %lld
",Mflow,Mcost);
return 0;
}