zoj 1455(差分約束)

題目鏈接:http://210.32.0.220/onlinejudge/showProblem.do?problemCode=1455

典型的差分約束題目, 不等式很好列但此題求的是滿足約束的最小值, 原來看到網上有最大值求最短路, 最小值求最長路的說法但本人覺得有點煩, 所以都轉化成求最短路, 所以要求加負號的最大值, 注意超級點的確立, 細節詳見代碼。


#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>

using namespace std;

const int N = 5005;
const int M = N << 4;
const int INF = 1000000000;

struct SPFA {
	
	struct Edge {
		int v, w;
		Edge* next;

		void init(int a, int b, Edge* e) {
			v = a, w = b, next = e;
		}
	};

	Edge E[M], * head[N], * it;
	bool inq[N];
	int cnt[N];
	queue<int> Q;
	int tot, n;
	int dis[N];

	void init(int n) {
		this->n = n;
		it = E;
		for (int i = 0; i < n; i++) {
			head[i] = 0;
		}
	}

	void add(int u, int v, int w) {
		it->init(v, w, head[u]);
		head[u] = it++;
	}

	bool run(int s) {
		for (int i = 0; i < n; cnt[i] = 0, inq[i] = 0, dis[i++] = INF);
		dis[s] = 0;
		Q.push(s);
		cnt[s] = 1;
		while (!Q.empty()) {
			int u = Q.front();
			inq[u] = 0;
			Q.pop();
			for (Edge* e = head[u]; e; e = e->next) {
				int v = e->v;
				if (dis[v] > dis[u] + e->w) {
					dis[v] = dis[u] + e->w;
					if(!inq[v]) {
						Q.push(v);
						inq[v] = 1;
						cnt[v]++;
						if (cnt[v] > n) return 0;
					}
				}
			}
		}
		return 1;
	}
}G;

char op[10];

int main() {
	int n, u, v, w, cas = 1;
	while (scanf("%d", &n), n) {
		int s = 0;
		G.init(2 * n + 1);
		for (int i = 1; i <= n; i++) {
			scanf("%d", &w);
			G.add(i + n, i, -w);
			G.add(i, i + n, w);			
		}
		
		for (int i = 1; i <= n; i++)
			G.add(s, i + n, 0);
		
		while (scanf("%s", op)) {
			if (op[0] == '#') break;
			scanf("%d%d", &u, &v);
			if (strcmp(op, "FAS") == 0) {
				G.add(u + n, v, 0);	
			}
			else if (strcmp(op, "FAF") == 0) {
				G.add(u + n, v + n, 0);
			}
			else if (strcmp(op, "SAF") == 0) {
				G.add(u, v + n, 0);
			}
			else {
				G.add(u, v, 0);
			}
		}

		printf("Case %d:\n", cas++);

		int st = INF;

		if (!G.run(s)) {
			puts("impossible\n");
		}
		else {

			for (int i = 1; i <= n; i++)
				st = min(st, G.dis[i]);

			for (int i = 1; i <= n; i++) {
				printf("%d %d\n", i, G.dis[i] - st);
			}
			puts("");
		}
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章