这个题题意就不用说了,想了半天。
思路就是把所有的最短路径边求出来,然后再以删掉该边的花费作为代价建图,设立源点和汇点,求最大流即可。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=2000;
const int maxm=50000;
const int inf=1<<29;
struct Node
{
int u;
int v;
int w;
int c;
}s[maxn*maxn];
struct Snode
{
int u,v;
}ee[maxn*maxn];
int x,y,n,m,e,des,st,head[maxn],nxt[maxm],cost[maxm],pnt[maxm],dist[maxn];
int we,whead[maxn],wpnt[maxm],wnxt[maxm],flow[maxm],level[maxn];
int f[maxn][maxn];
bool vis[maxn];
queue<int> q;
void AddEdge(int u,int v,int c)
{
pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;
pnt[e]=u;nxt[e]=head[v];cost[e]=c;head[v]=e++;
}
int Spfa(int st,int des)
{
for(int i=0;i<=n;i++)
dist[i]=inf;
dist[st]=0;
while(!q.empty())
q.pop();
q.push(st);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=nxt[i])
{
int v=pnt[i];
if(dist[v]>dist[u]+cost[i])
{
dist[v]=dist[u]+cost[i];
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
return dist[des];
}
void AddEdgeW(int u,int v,int f)
{
wpnt[we]=v;wnxt[we]=whead[u];flow[we]=f;whead[u]=we++;
wpnt[we]=u;wnxt[we]=whead[v];flow[we]=0;whead[v]=we++;
}
bool BFS(int st)
{
memset(level,0,sizeof(level));
while(!q.empty())
q.pop();
q.push(st);
level[st]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==des)
return true;
for(int i=whead[u];i!=-1;i=wnxt[i])
if(flow[i]&&!level[wpnt[i]])
{
level[wpnt[i]]=level[u]+1;
q.push(wpnt[i]);
}
}
return level[des];
}
int DFS(int u,int sum)
{
if(u==des)
return sum;
for(int i=whead[u],t;i!=-1;i=wnxt[i])
{
if(flow[i]&&level[wpnt[i]]==level[u]+1&&(t=DFS(wpnt[i],min(sum,flow[i]))))
{
flow[i]-=t;
flow[i^1]+=t;
return t;
}
}
return level[u]=0;
}
int maxflow()
{
int ans=0;
while(BFS(st))
{
while(1)
{
int val=DFS(st,inf);
if(!val)
break;
ans+=val;
}
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)&&(n||m))
{
memset(head,-1,sizeof(head));
e=we=0;
scanf("%d%d",&x,&y);
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&s[i].u,&s[i].v,&s[i].w,&s[i].c);
AddEdge(s[i].u,s[i].v,s[i].w);
}
int ans=Spfa(x,y);
memset(whead,-1,sizeof(whead));
memset(f,0,sizeof(f));
int cnt=0;
for(int i=0;i<m;i++)
{
if(dist[s[i].u]+s[i].w==dist[s[i].v])
{
if(!f[s[i].u][s[i].v])
{
ee[cnt].u=s[i].u;
ee[cnt++].v=s[i].v;
}
f[s[i].u][s[i].v]+=s[i].c;
}
if(dist[s[i].v]+s[i].w==dist[s[i].u])
{
if(!f[s[i].v][s[i].u])
{
ee[cnt].u=s[i].v;
ee[cnt++].v=s[i].u;
}
f[s[i].v][s[i].u]+=s[i].c;
}
}
for(int i=0;i<cnt;i++)
AddEdgeW(ee[i].u,ee[i].v,f[ee[i].u][ee[i].v]);
st=x,des=y;
printf("%d\n",maxflow());
}
return 0;
}