POJ 3169レイアウト(差動拘束システム)

トピックリンク

効果の件名:

牛Nの合計、良好な関係mlのメッセージ牛を有し、悪いMD牛関係情報を有していて、三つの要素、三つの要素Aの次mlの行の最初の行に対応する入力、 B、D、及びBは、ウシの牛を表すが、離れDより三つの要素、B、Dの次MD行を望ましくない、そしてBは、少なくとも距離Dジョブでなければならないウシ牛を表します。距離が無限出力-2、-1出力ない溶液場合であれば、最大距離番号1および番号Nウシ牛を求めます。

アイデア1

アイデア2


1つのアイデア:

まず、最大距離であることを、nは1〜で求めて、それを考慮

d[n] - d[1] <= t

図1は、出発点として見ることができるN末端であり、あなたがアイテムを移動しなければなりません

d[n] <= d[1] + t

不等式だけ最短後スラックのようであり、従ってnに1を求める最短に対応します

はるかに簡単、タイトル情報によると、以下があります

a - b <= D
c - d >= D

转换为

a <= b + D
d <= c - D

アイデアは、最短経路、すなわちに変換する最も短絡、不等式の上記の分析を解決することを目的とするため、このような変換であります

if(d[v] > d[u] + w(u, v)){
    d[v] = d[u] + w[u, v];
}

松弛操作前:
d[v] > d[u] + w(u, v)

松弛操作后:
d[v] <= d[u] + w(u, v)

-Dの重量の2つの縁部> D - - 変換後、A、Bはそれぞれ、エッジを構築することができ> Dの重量を有すると、c

ソースポイントに要求への最短パスを作成した後

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 51000;
int n, ml, md;
int head[N], nex[N], to[N], edge[N];
int cnt;
int c[N];
bool v[N];
int d[N];
struct SPFA {
	SPFA() {
		mem(head, -1);
		mem(nex, -1);
		mem(c, 0);
		mem(v, 0);
		cnt = 0;
		mem(d, 0x3f);
	}
	void init() {
		SPFA();
	}
	void add(int a, int b, int c) {
		++cnt;
		to[cnt] = b;
		edge[cnt] = c;
		nex[cnt] = head[a];
		head[a] = cnt;
	}
	int spfa(int begin, int end) {
		d[begin] = 0;
		c[begin]++;
		v[begin] = 1;
		queue<int> q;
		q.push(begin);
		bool f = true;
		while (!q.empty()) {
			int t = q.front();
			q.pop();
			if (c[t] > n) {
				f = 0;
				break;
			}
			c[t]++;
			v[t] = 0;
			for (int i = head[t]; i != -1; i = nex[i]) {
				int y = to[i];
				int dist = edge[i];
				if (d[y] > d[t] + dist) {
					d[y] = d[t] + dist;
					if (!v[y]) {
						v[y] = 1;
						q.push(y);
					}
				}
			}
		}
		if (f) {
			return d[end];
		}
		else return -404;
	}
}sp;
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n >> ml >> md) {
		sp.init();
		for (int i = 0; i < ml; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(a, b, c);
		}
		for (int i = 0; i < md; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(b, a, -c);
		}
		int res = sp.spfa(1, n);
		if (res == inf) {
			cout << "-2\n";
		}
		else if (res == -404) {
			cout << "-1\n";
		}
		else cout << res << "\n";
	}
	return 0;
}

2つのアイデア:

もちろん、また最長の道路、二番目に長い道路によって解決することができ、解決のためのアイデアは言いました

それは1からnまでの最大距離であるため、それはのように表すことができます。

d[n] - d[1] <= t

转换为

d[1] - d[n] >= -t

进一步化为

d[1] >= d[n] - t

これは、緩和操作で不平等を解決するために、最長の方法に沿ったものです

私たちは、あなたが1からnまでの最長パスを見つけることができることを意味、トンまだ、我々は結果を見つけるシークです:-t(負ノート)、nは1である最長の道路反対側の番号を取るだけの必要性ことができます。

そして、上記のプロセスがありますし、設立の側が緩和操作後、道路の最長辺に沿って建設されたとき、興味は約書き込みに上記の試みを参照することができれば、それを繰り返すことはしませんほぼ同じ、私はコードを貼り付けます

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 51000;
int n, ml, md;
int head[N], nex[N], to[N], edge[N];
int cnt;
int c[N];
bool v[N];
int d[N];
struct SPFA {
	SPFA() {
		mem(head, -1);
		mem(nex, -1);
		mem(c, 0);
		mem(v, 0);
		cnt = 0;
		mem(d, 0x3f);
		for (int i = 0; i < N; i++)d[i] = -d[i];
	}
	void init() {
		SPFA();
	}
	void add(int a, int b, int c) {
		++cnt;
		to[cnt] = b;
		edge[cnt] = c;
		nex[cnt] = head[a];
		head[a] = cnt;
	}
	int spfa(int begin, int end) {
		d[begin] = 0;
		c[begin]++;
		v[begin] = 1;
		queue<int> q;
		q.push(begin);
		bool f = true;
		while (!q.empty()) {
			int t = q.front();
			q.pop();
			if (c[t] > n) {
				f = 0;
				break;
			}
			c[t]++;
			v[t] = 0;
			for (int i = head[t]; i != -1; i = nex[i]) {
				int y = to[i];
				int dist = edge[i];
				if (d[y] < d[t] + dist) {
					d[y] = d[t] + dist;
					if (!v[y]) {
						v[y] = 1;
						q.push(y);
					}
				}
			}
		}
		if (f) {
			return d[end];
		}
		else return -404;
	}
}sp;
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n >> ml >> md) {
		sp.init();
		for (int i = 0; i < ml; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(b, a, -c);
		}
		for (int i = 0; i < md; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(a, b, c);
		}
		int res = sp.spfa(n, 1);
		if (res == -inf) {
			cout << "-2\n";
		}
		else if (res == -404) {
			cout << "-1\n";
		}
		else cout << -res << "\n";
	}
	return 0;
}

 

公開された143元の記事 ウォン称賛11 ビュー8185

おすすめ

転載: blog.csdn.net/weixin_43701790/article/details/104062754