首先求一遍最短路,然后把最短路径上的边存下来,我们要删除的边也一定是这上面的边,建图方式就是看是否满足d[a]=d[b]+map[a][b]
然后一遍最小割就能求到最小花费。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #include<string> #define eps 1e-12 #define INF 0x7fffffff #define maxn 3005 using namespace std; int n,m; int en; int st,ed; //源点和汇点 int dis[maxn] ;//dis[i],表示 到 原点 s 的 层数 int que[9999999]; struct edge { int to,c,next; }; edge e[9999999]; int head[maxn]; void add(int a,int b,int c) { e[en].to=b; e[en].c=c; e[en].next=head[a]; head[a]=en++; e[en].to=a; e[en].c=0; e[en].next=head[b]; head[b]=en++; } int bfs() { memset(dis,-1,sizeof(dis)); dis[st]=0; int front=0,rear=0; que[rear++]=st; while(front<rear) { int j=que[front++]; for(int k=head[j];k!=-1;k=e[k].next) { int i=e[k].to; if(dis[i]==-1&&e[k].c) { dis[i] = dis[j]+ 1 ; que[rear++]=i; if(i==ed) return true; } } } return false; } int dfs(int x,int mx) { int i,a; if(x==ed) return mx ; int ret=0; for(int k=head[x];k!=-1&&ret<mx;k=e[k].next) { if(e[k].c&&dis[e[k].to]==dis[x]+1) { int dd=dfs(e[k].to,min(e[k].c,mx)); e[k].c-=dd; e[k^1].c+=dd; mx-=dd; ret+=dd; } } if(!ret) dis[x]=-1; return ret; } void init() { en=0; memset(head,-1,sizeof(head)); } int dinic() { int tmp=0; int maxflow=0; while(bfs()) { while(tmp=dfs(st,INF)) maxflow+=tmp; } return maxflow; } int in[10005]; int d[10005]; struct node2 { int next; int w; }t; vector<node2> v[1005]; void SPFA(int st) { queue<int> Q; memset(in,0,sizeof(int)*(n+1)); memset(d,0x3f,sizeof(int)*(n+1)); Q.push(st); in[st]=1; d[st]=0; int tmp; while(!Q.empty()) { tmp=Q.front();Q.pop(); in[tmp]=0; for(int i=0;i<v[tmp].size();i++) { int to=v[tmp][i].next; int w=v[tmp][i].w; if(d[to]>d[tmp]+w) { d[to]=d[tmp]+w; if(!in[to]) { in[to]=1; Q.push(to); } } } } } int ee[100005][6]; int main() { int x,y,a,b,c,e; while(scanf("%d%d",&n,&m)!=EOF) { if(!n&&!m) break; init(); for(int i=1;i<=n;i++) v[i].clear(); scanf("%d%d",&x,&y); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&a,&b,&c,&e); ee[i][0]=a; ee[i][1]=b; ee[i][2]=c; ee[i][3]=e; t.w=c; t.next=b; v[a].push_back(t); t.next=a; v[b].push_back(t); } SPFA(x); st=x; ed=y; for(int i=1;i<=m;i++) { if(d[ee[i][1]]==d[ee[i][0]]+ee[i][2]) { add(ee[i][0],ee[i][1],ee[i][3]); } if(d[ee[i][0]]==d[ee[i][1]]+ee[i][2]) { add(ee[i][1],ee[i][0],ee[i][3]); } } printf("%d\n",dinic()); } }
CodingTrip - 携程编程大赛 (决赛)1004 最短路最小割,布布扣,bubuko.com
CodingTrip - 携程编程大赛 (决赛)1004 最短路最小割
原文:http://blog.csdn.net/t1019256391/article/details/23705511