调了一晚上的最小费用最大流。
目前我得到的是 73 分代码,还 WA 了几个点。
不过这份代码之前连样例都过不去。
我输中量发现,我的代码在 spfa 松弛过程中判定了 3≥16。
我觉得很离谱,于是查错,但是并没有发现任何错误。
于是我怀疑编译器抽风了。
我在松弛语句内部又加了一句,在第 51 行,按理说这一行本来根本不会起到作用,但是,加了之后,他过了样例还拿了 73 分。
谁能告诉我这是怎么回事,如果是我代码出了问题或者是我自己 sb 了,请指出来,或者说 g++ 被 hack 了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e3+5;
const int maxm=5e4+5;
int n,m,s,t;
int head[maxn];
struct EDGE
{
int to,nxt;
ll w,c;
}edge[maxm<<1];
int cnt=1;
void add(int u,int to,int w,int c)
{
edge[++cnt].to=to;
edge[cnt].w=w;
edge[cnt].c=c;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
struct Path
{
int fa,edge;
}path[maxn];
ll dis[maxn];
bool inq[maxn];
int que[maxn],qhead,qtail;
bool spfa()
{
memset(dis,0x3f3f3f3f,sizeof dis);
memset(path,0,sizeof path);
memset(inq,0,sizeof inq);
qhead=1,qtail=0;
que[++qtail]=s;
dis[s]=0;
while(qhead<=qtail)
{
int u=que[qhead++];
inq[u]=0;
// printf("(spf) u: %d\n",u);
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
// printf("(spf) to: %d dis: %lld\n",to,dis[to]);
if(!edge[i].w)continue;
ll a=dis[to],b=dis[u]+edge[i].c;
// printf("a: %lld b: %lld\n",a,b);
if(a>b&&a>b);
{
if(a-b<=0)continue;
// printf("%lld>%lld\n",a,b);
// printf("(spf) to: %d dis: %lld\n",to,dis[to]);
dis[to]=dis[u]+edge[i].c;
path[to].fa=u;
path[to].edge=i;
if(!inq[to])
{
inq[to]=1;
que[++qtail]=to;
}
}
}
}
return dis[t]!=dis[0];
}
void EK()
{
ll ans1=0,ans2=0;
while(spfa())
{
ll imin=1e18;
for(int u=t;u!=s;u=path[u].fa)
{
// printf("u: %d\n",u);
imin=std::min(imin,edge[path[u].edge].w);
}
for(int u=t;u!=s;u=path[u].fa)
{
edge[path[u].edge].w-=imin;
edge[path[u].edge^1].w+=imin;
}
// printf("imin: %lld\n",imin);
ans1+=imin;
ans2+=dis[t]*imin;
}
printf("%lld %lld",ans1,ans2);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
int u,v,w,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&u,&v,&w,&c);
add(u,v,w,c);
add(v,u,0,-c);
}
EK();
return 0;
}