#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define M 40009
#define N 2000
using namespace std;
struct edge{
int y,next,f,d;
bool vis;
}e[M];
int cnt,p[N],gap[N],h[N],n,m,source,sink,X,Y;
bool vis[N];
int dis[N];
void add(int a,int b,int d,int f){
e[cnt].y=b;
e[cnt].f=f;
e[cnt].d=d;
e[cnt].next=p[a];
e[cnt].vis=0;
p[a]=cnt++;
e[cnt].y=a;
e[cnt].d=d;
e[cnt].f=f;
e[cnt].next=p[b];
e[cnt].vis=0;
p[b]=cnt++;
}
void init(){
memset(p,-1,sizeof(p));
memset(h,0,sizeof(h));
memset(gap,0,sizeof(gap));
memset(vis,0,sizeof(vis));
memset(dis,0xf,sizeof(dis));
cnt=0;
source=0;
sink=n+1;
gap[0]=n+2;//总点数
}
int dfs(int x,int f){
if(x==sink)
return f;
int i,mh=n-1,lf=f,d,y;
for(i=p[x];i!=-1;i=e[i].next){
y=e[i].y;
if(e[i].vis==0)
continue;
if(e[i].f>0){
if(h[x]==h[y]+1){
d=min(e[i].f,lf);
d=dfs(y,d);
e[i].f-=d;
e[i^1].f+=d;
lf-=d;
if(h[source]>=n)
return f-lf;
if(lf==0)
break;
}
mh=min(mh,h[y]);
}
}
if(f==lf){
gap[h[x]]--;
if(gap[h[x]]==0)
h[source]=n;
h[x]=mh+1;
gap[h[x]]++;
}
return f-lf;
}
int spfa(){
queue<int>q;
q.push(X);
vis[X]=1;
dis[X]=0;
while(!q.empty()){
int f=q.front();
vis[f]=0;
q.pop();
for(int i=p[f];i!=-1;i=e[i].next){
int y=e[i].y;
if(dis[y]>dis[f]+e[i].d){
dis[y]=dis[f]+e[i].d;
if(!vis[y])
q.push(y),vis[y]=1;
}
}
}
return dis[Y];
}
void check(){
queue<int>q;
q.push(X);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(dis[i]>dis[Y])
continue;
for(int j=p[i];j!=-1;j=e[j].next){
if(dis[e[j].y]>dis[Y]||dis[i]+e[j].d>dis[e[j].y])//判断边是否是最短路上的边
continue;
e[j].vis=1;
// printf("x=%d y=%d f=%d\n",i,e[j].y,e[j].f);
}
}
}
int main(){
int i,j,k,x,y,f,d;
while(scanf("%d%d",&n,&m)&&n&&m){
init();
scanf("%d%d",&X,&Y);
add(source,X,0,1e8);
e[cnt-1].vis=1;
e[cnt-2].vis=1;
add(Y,sink,0,1e8);
e[cnt-1].vis=1;
e[cnt-2].vis=1;
while(m--){
scanf("%d%d%d%d",&x,&y,&d,&f);
add(x,y,d,f);
}
spfa();
check();
int s=0;
n+=2;
while(h[source]<n)
s+=dfs(source,1e8);
printf("%d\n",s);
}
return 0;
}
先求出最短路,然后遍历每条边,如果边长大于两边到起点的距离只差,则该边不可走
将删除的代价作为流量,跑一边最大流(最小割)就是结果