传送门
先跑一发最短路,求出有用边,
然后就是裸的网络流了。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 1e9
#define ll long long
using namespace std;
struct data{
int from,to,next,val,time;
}e[250005],ed[250005];
int q[1005],f[505][505],head[1005],dis[1005];
int tot=1,n,m,ans;
inline void lll(int x,int y,int u){
tot++;
ed[tot].to=y;
ed[tot].val=u;
ed[tot].next=head[x];
head[x]=tot;
}
inline void kkk(int x,int y,int u){
lll(x,y,u);
lll(y,x,0);
}
inline int bfs(){
int h=0,t=1,x;
memset(dis,-1,sizeof(dis));
dis[1]=0;
q[1]=1;
while (h!=t){
x=q[++h];
for (int i=head[x];i;i=ed[i].next)
if (ed[i].val&&!~dis[ed[i].to]){
dis[ed[i].to]=dis[x]+1;
q[++t]=ed[i].to;
if (ed[i].to==n) return 1;
}
}
return 0;
}
int dfs(int x,int flow){
int i,left=flow,tmp;
if (x==n) return flow;
for (int i=head[x];i&&left;i=ed[i].next)
if (ed[i].val&&dis[ed[i].to]==dis[x]+1){
tmp=dfs(ed[i].to,min(left,ed[i].val));
left-=tmp;
ed[i].val-=tmp;
ed[i^1].val+=tmp;
}
if (left) dis[x]=-1;
return flow-left;
}
int main(){
scanf("%d%d",&n,&m);
memset(f,0x3f,sizeof(f));
for (int i=1;i<=n;i++) f[i][i]=0;
for (int i=1;i<=m;i++){
scanf("%d%d%d%d",&e[i].from,&e[i].to,&e[i].time,&e[i].val);
f[e[i].from][e[i].to]=f[e[i].to][e[i].from]=e[i].time;
}
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
printf("%d\n",f[1][n]);
for (int i=1;i<=m;i++){
if (f[1][e[i].from]+f[e[i].to][n]+e[i].time==f[1][n])
kkk(e[i].from,e[i].to,e[i].val);
if (f[1][e[i].to]+f[e[i].from][n]+e[i].time==f[1][n])
kkk(e[i].to,e[i].from,e[i].val);
}
while (bfs()) ans+=dfs(1,inf);
printf("%d",ans);
}