一般用来求解在 M M M个不等式的限制下,是否存在解,最大解,最小解。
- 判断存在解:spfa判负环
- 最大解:最短路(三角不等式)
- 最小解:最长路(三角不等式)
POJ 3169
最大距离:最短路
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <time.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
using namespace std;
const int maxn = 1e3 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
vector<P>g[maxn];
int dis[maxn], vis[maxn], cnt[maxn];
int n, m, k;
struct cmp {
bool operator()(int x, int y){
return dis[x] < dis[y];
}
};
int Spfa(int s) {
mem(dis, inf);
mem(vis, 0);
dis[s] = 0;
priority_queue<int> que;
que.push(s);
cnt[s]++;
vis[s] = 1;
while (!que.empty()) {
int u = que.top();
que.pop();
vis[u] = 0;
int len = g[u].size();
for (int i = 0; i < len; ++i) {
int v = g[u][i].second;
int c = g[u][i].first;
if (dis[v] > dis[u] + c) {
dis[v] = dis[u] + c;
if (!vis[v]) {
que.push(v);
vis[v] = 1;
cnt[v]++;
if (cnt[v] > n) return -1;
}
}
}
}
return dis[n] == inf;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
scanf("%d%d%d", &n, &m, &k);
int u, v, w;
for (int i = 0; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(make_pair(w, v));
}
for (int i = 0; i < k; ++i) {
scanf("%d%d%d", &u, &v, &w);
g[v].push_back(make_pair(-w, u));
}
int flag = Spfa(1);
if (flag == -1) puts("-1");
if (flag == 1) puts("-2");
if (flag == 0) printf("%d\n", dis[n]);
return 0;
}
HDU 3440
最大距离:最短路
建边的时候判断相邻距离距离是否
>
M
> M
>M,并按照小边到大边建边
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
vector<P>g[maxn];
int dis[maxn], vis[maxn], cnt[maxn];
int n, m;
int Spfa(int s, int e) {
queue<int> que;
mem(dis, inf);
mem(vis, 0);
mem(cnt, 0);
dis[s] = 0;
que.push(s);
cnt[s]++;
vis[s] = 1;
while (!que.empty()) {
int u = que.front();
que.pop();
vis[u] = 0;
int len = g[u].size();
for (int i = 0; i < len; ++i) {
int v = g[u][i].second;
int c = g[u][i].first;
if (dis[v] > dis[u] + c) {
dis[v] = dis[u] + c;
if (!vis[v]) {
que.push(v);
vis[v] = 1;
cnt[v]++;
if (cnt[v] > n) return -1;
}
}
}
}
if (dis[e] == inf) return -2;
return dis[e];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T, Case = 1, ans;
cin >> T;
while (T--) {
cout << "Case " << Case++ << ": ";
cin >> n >> m;
ans = 0;
for (int i = 0; i < n; ++i) g[i].clear();
vector<int> a(n), b(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
iota(b.begin(), b.end(), 0);
sort(b.begin(), b.end(), [&](int x, int y){
if (a[x] != a[y]) return a[x] < a[y];
else return x < y;
});
for (int i = 0; i < n-1; ++i) {
g[i+1].push_back(make_pair(-1, i));
int u = min(b[i], b[i+1]);
int v = max(b[i], b[i+1]);
g[u].push_back(make_pair(m, v));
if (u - v > m) {
ans = -1;
break;
}
}
if (ans == -1) {
cout << -1 << endl;
continue;
}
int s = min(b[0], b[n-1]);
int e = max(b[n-1], b[0]);
int ans = Spfa(s, e);
cout << ans << endl;
}
return 0;
}
POJ 1201
区间约束
最小解:最长路
满足区间建边之后,还要考虑区间的合法性
0
≤
s
u
m
[
n
]
−
s
u
m
[
n
−
1
]
≤
1
0 \le sum[n] - sum[n-1] \le 1
0≤sum[n]−sum[n−1]≤1
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <numeric>
#include <algorithm>
#include <cstring>
#include <time.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
vector<P> g[maxn];
int vis[maxn], dis[maxn], cnt[maxn];
void add(int u, int v, int c) {
g[u].push_back(make_pair(c, v));
}
int Spfa(int s, int e) {
mem(vis, 0);
mem(dis, -inf);
mem(cnt, 0);
dis[s] = 0;
cnt[s] = 1;
vis[s] = 1;
queue<int> que;
que.push(s);
while (!que.empty()) {
int f = que.front();
que.pop();
vis[f] = 0;
int len = g[f].size();
for (int i = 0; i < len; ++i) {
P x = g[f][i];
if (dis[x.second] >= dis[f] + x.first) continue;
dis[x.second] = dis[f] + x.first;
if (vis[x.second] == 0) {
vis[x.second] = 1;
que.push(x.second);
if (++cnt[x.second] >= e) return -1;
}
}
}
return dis[e];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n, s = 1e9, e = 0;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
s = min(a, s);
e = max(b+1, e);
add(a, b+1, c);
}
for (int i = s; i < e; ++i) {
add(i, i+1, 0);
add(i+1, i, -1);
}
int ans = Spfa(s, e);
printf("%d\n", ans);
return 0;
}