挺有意思的一题,最小路径之后最大流
/**************************************************************
作者:陈新
邮箱: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;
}
}
}