挺有意思的一题,最小路径之后最大流
/************************************************************** 作者:陈新 邮箱:cx2pirate@gmail.com 用途:ustc1280.cpp(图) 时间:2014 4月17日 21:55 测试:未验证 思路:先求最短路径,根据dis[v] = dis[u] + dis(u,v)获得包含最短路径所有边的一个子图(可能还包括 了其他边,根据最大流最小割,再求最大流就是最小代价。 *************************************************************/ #include <cstdio> #include <memory.h> #include <stack> #include <vector> #include <queue> #define MAXV 1005 //最大定点数 #define MAXE 10005 //最大边数 #define MAX_INT 0x7fffffff using namespace std; typedef struct{ int v,c,w,next; }EDGE; int n,m,sour,dest,nEdge; EDGE map1[MAXE]; //map1保存原图,map2保存map1中最短路径上的所有边 int head[MAXV]; int map2[MAXV][MAXV]; int dis[MAXV]; bool inQue[MAXV]; bool vis[MAXV]; int pre[MAXV]; void addEdge(int u,int v,int w,int c); void spfa(); void init(); void traceRoute(); bool bfs(); int dicnic(); int update(); int main(){ int cnt = 1; while(scanf("%d%d",&n,&m) && !(n == 0 && m == 0)){ init(); scanf("%d%d",&sour,&dest); int u,v,w,c; for(int i = 0;i < m;i++){ scanf("%d%d%d%d",&u,&v,&w,&c); addEdge(u,v,w,c); addEdge(v,u,w,c); } spfa(); traceRoute(); int cost = dicnic(); printf("Case %d: %d\n",cnt++,cost); } return 0; } int dicnic(){ int sum = 0; while(bfs()){ sum += update();; } return sum; } bool bfs(){ for(int i = 1;i <= n;i++){ vis[i] = false; pre[i] = -1; } queue<int> que; que.push(sour); vis[sour] = true; while(!que.empty()){ int u = que.front(); que.pop(); if(u == dest){ return true; } for(int v = 1;v <= n;v++){ if(!vis[v] && map2[u][v] > 0){ vis[v] = true; que.push(v); pre[v] = u; } } } return false; } int update(){ int v = dest; int min = MAX_INT; while(pre[v] != -1){ min = min < map2[pre[v]][v] ? min : map2[pre[v]][v]; v = pre[v]; } v = dest; while(pre[v] != -1){ map2[pre[v]][v] -= min; map2[v][pre[v]] += min; v = pre[v]; } return min; } void traceRoute(){ //有不是最短路径的边也被添加到新图中,但对最小割无关紧要 memset(vis,false,sizeof(vis)); queue<int> que; que.push(sour); vis[sour] = true; while(!que.empty()){ int u = que.front(); que.pop(); int i = head[u]; while(i != -1){ EDGE e = map1[i]; if(dis[e.v] == dis[u] + e.w){ map2[u][e.v] += e.c; if(!vis[e.v]){ que.push(e.v); vis[e.v] = true; } } i = e.next; } } } void addEdge(int u,int v,int w,int c){ map1[nEdge].v = v; map1[nEdge].w = w; map1[nEdge].c = c; map1[nEdge].next = head[u]; head[u] = nEdge++; } void spfa(){ queue<int> que; que.push(sour); inQue[sour] = true; dis[sour] = 0; while(!que.empty()){ int u = que.front(); que.pop(); inQue[u] = false; int i = head[u]; while(i != -1){ EDGE e = map1[i]; if(dis[e.v] > dis[u] + e.w){ dis[e.v] = dis[u] + e.w; if(!inQue[e.v]){ que.push(e.v); inQue[e.v] = true; } } i = e.next; } } } void init(){ nEdge = 0; for(int i = 1;i <= n;i++){ head[i] = -1; dis[i] = MAX_INT; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ map2[i][j] = 0; } } }