挺有意思的一题,最小路径之后最大流

 /**************************************************************
  作者:陈新
  邮箱: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;
		}
	}
}



 

 posted on 2014-04-21 18:28  莫扎特的代码  阅读(198)  评论(0编辑  收藏  举报