题目
描述 Description
给出一有向图,图中每条边都被标上了关系运算符‘<’,‘>’,‘=’。现在要给图中每个顶点标上一个大于等于0,小于等于k的某个整数使所有边上的符号得到满足。若存在这样的k,则求最小的k,若任何k都无法满足则输出NO。
例如下表中最小的k为2。
结点1>结点2
结点2>结点3
结点2>结点4
结点3=结点4
如果存在这样的k,输出最小的k值;否则输出‘NO’。
输入格式 Input Format
共二行,第一行有二个空格隔开的整数n和m。n表示G的结点个数,m表示G的边数,其中1<=n<=1000, 0<=m<=10000。全部结点用1到n标出,图中任何二点之间最多只有一条边,且不存在自环。
第二行共有3m个用空格隔开的整数,第3i-2和第3i-1(1<=i<=m)个数表示第i条边的顶点。第3i个数表示第i条边上的符号,其值用集合{-1,0,1}中的数表示:-1表示‘<’, 0 表示‘=’, 1表示‘>’。
输出格式 Output Format
仅一行,如无解则输出‘NO’;否则输出最小的k的值。
样例输入 Sample Input
4 4
1 2 -1 2 3 0 2 4 -1 3 4 -1
样例输出 Sample Output
2
题解
差分约束的题。
spfa跑最长路+判负环。
code
#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <list>
#include <map>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define _ 0
#define fup(i, a, b) for (i = a; i <= b; ++i)
#define fdown(i, a, b) for (i = a; i >= b; --i)
typedef long long ull;
const int maxn = 1e6;
const int inf = 0x3f3f3f3f;
namespace millope {
inline void swap(int a, int b) { a ^= b; b ^= a; a^= b; }
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a > b ? b : a; }
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch - '0'); ch = getchar(); }
return s * w;
}
}
using namespace millope;
int n;
int m;
int tot;
int ans;
int cnt[maxn];
int link[maxn];
int dis[maxn];
bool vis[maxn];
struct Edge { int next, to, dis; } e[maxn];
inline void add(int from ,int to, int dis) {
e[++tot].to = to;
e[tot].dis = dis;
e[tot].next = link[from];
link[from] = tot;
}
void spfa(int k) {
std::queue<int> q;
memset(dis, 0xcf, sizeof(dis));
memset(vis, false, sizeof(vis));
dis[k] = 0, vis[k] = true;
q.push(k); cnt[k]++;
while (!q.empty()) {
int u = q.front();
q.pop(); vis[u] = false;
for (int i = link[u]; i; i = e[i].next) {
int v = e[i].to;
if (dis[v] < dis[u] + e[i].dis) {
dis[v] = dis[u] + e[i].dis;
if (!vis[v]) {
vis[v] = true;
q.push(v);
cnt[v]++;
// printf("%d===\n", cnt[v]);
if (cnt[v] > n) {
printf("NO\n");
exit(0);
}
}
}
}
}
}
int main() {
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
n = read(), m = read(); ans = -inf;
for (int i = 1, a, b, c; i <= m; ++i) {
a = read(), b = read(), c= read();
if (c == -1) add(b, a, 1);
else if (c == 0) add(a, b, 0), add(b, a, 0);
else if (c == 1) add(a, b, 1);
}
for (int i = 1; i <= n; ++i) {
add(0, i, 0);
}
spfa(0);
for (int i = 1; i <= n; ++i) {
ans = max(ans, dis[i]);
}
printf("%d\n", ans);
return (0^_^0);
}