POJ 2175 Floyd-Warshall

Titulo

Portal POJ 2175

Solución

El flujo es demasiado grande y el costo mínimo es arrodillarse. El problema solo requiere que la respuesta sea mejor que el plan actual. Use Floyd-Warshall para encontrar un círculo negativo en la carretera Zengguang, y aumente a lo largo del círculo negativo para obtener una corriente menos costosa. La implementación considera que existe una correspondencia biunívoca entre la cantidad de personas en la ciudad proporcionada por el esquema provisto, luego el punto fuente llega al borde de la ciudad y el punto fuente puede no ser considerado cuando se busca el círculo negativo.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
using namespace std;

#define MAX_N 100
#define MAX_M 100
int N, M;
int X[MAX_N], Y[MAX_N], B[MAX_N];
int P[MAX_N], Q[MAX_N], C[MAX_N];
int E[MAX_N][MAX_M];

#define MAX_V 202
int dist[MAX_V][MAX_V];
int prev[MAX_V][MAX_V];
bool used[MAX_V];

void solve(){
	memset(dist, 0x3f, sizeof(dist));
	int t = N + M, V = t + 1;
	// 建立邻接矩阵,为所有增广路赋对应权值
	for(int j = 0; j < M; j++){
		int s = 0;
		for(int i = 0; i < N; i++){
			int d = abs(X[i] - P[j]) + abs(Y[i] - Q[j]) + 1;
			s += E[i][j];
			if(E[i][j] > 0) dist[N + j][i] = -d;
			if(E[i][j] < min(B[i], C[j])) dist[i][N + j] = d;
		}
		if(s > 0) dist[t][N + j] = 0;
		if(s < C[j]) dist[N + j][t] = 0;
	}
	for(int i = 0; i < V; i++){
		for(int j = 0; j < V; j++){
			prev[i][j] = i;
		}
	}
	// Floyd-Warshall
	for(int k = 0; k < V; k++){
		for(int i = 0; i < V; i++){
			for(int j = 0; j < V; j++){
				if(dist[i][j] > dist[i][k] + dist[k][j]){
					dist[i][j] = dist[i][k] + dist[k][j];
					prev[i][j] = prev[k][j];
					if(i == j && dist[i][j] < 0){
						// 找到负圈
						memset(used, 0, sizeof(used));
						for(int v = i; !used[v]; v = prev[i][v]){
							used[v] = 1;
							if(v != t && prev[i][v] != t){
								if(v >= N) ++E[prev[i][v]][v - N];
								else --E[v][prev[i][v] - N];
							}
						}
						printf("SUBOPTIMAL\n");
						for(int i = 0; i < N; i++){
							for(int j = 0; j < M; j++){
								printf("%d%c", E[i][j], j == M - 1 ? '\n' : ' ');
							}
						}
						return;
					}
				}
			}
		}
	}
	printf("OPTIMAL\n");
}

int main(){
	while(~scanf("%d%d", &N, &M)){
		for(int i = 0; i < N; i++) scanf("%d%d%d", X + i, Y + i, B + i);
		for(int i = 0; i < M; i++) scanf("%d%d%d", P + i, Q + i, C + i);
		for(int i = 0; i < N; i++){
			for(int j = 0; j < M; j++){
				scanf("%d", &E[i][j]);
			}
		}
		solve();
	}
	return 0;
}
110 artículos originales publicados · Me gusta1 · Visitas 2051

Supongo que te gusta

Origin blog.csdn.net/neweryyy/article/details/105394788
Recomendado
Clasificación