You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010, M = 600010;
int n, m;
int h[N], hs[N], e[M], ne[M], w[M], idx;
void add(int h[], int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int dist[N];
// tarjan求scc
int dfn[N], low[N], ts, stk[N], top, in_stk[N];
int id[N], scc_cnt, sz[N];
void tarjan(int u) {
dfn[u] = low[u] = ++ts;
stk[++top] = u;
in_stk[u] = 1;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (in_stk[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
++scc_cnt;
int x;
do {
x = stk[top--];
in_stk[x] = 0;
id[x] = scc_cnt;
sz[scc_cnt]++;
} while (x != u);
}
}
int main() {
scanf("%d %d", &n, &m);
memset(h, -1, sizeof h);
memset(hs, -1, sizeof hs);
// 0号超级源点
// ∵ 恒星的亮度最暗是 1
// ∴ 0 ~ i 有一条边权为1的边
for (int i = 1; i <= n; i++) add(h, 0, i, 1);
// 求最小->求所有下界的最大->最长路 √
while (m--) {
int t, a, b;
scanf("%d %d %d", &t, &a, &b);
if (t == 1) // a=b
add(h, b, a, 0), add(h, a, b, 0);
else if (t == 2) // a < b --> b>=a+1
add(h, a, b, 1);
else if (t == 3) // a>=b+0
add(h, b, a, 0);
else if (t == 4) // a>=b+1
add(h, b, a, 1);
else
add(h, a, b, 0); // b>=a+0
}
// 超级源点+强连通分量+缩点
tarjan(0);
unordered_set<LL> S; // 对连着两个不同强连通分量的边进行判重
for (int u = 0; u <= n; u++) { // 添加上超级源点就是n+1个点
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
int a = id[u], b = id[v];
LL hash = a * 1000000ll + b; // 新两点a,b之间的Hash值防止出现重边
if (a == b) {
if (w[i] > 0) { // 在同一个强连通分量中存在边权大于0的边
puts("-1"); // 必然有正环,最长路存在正环,原不等式组无解
exit(0);
}
} else if (!S.count(hash))
add(hs, a, b, w[i]); // 建新图
}
}
for (int u = scc_cnt; u; u--) // 倒序输出拓扑序
for (int i = hs[u]; ~i; i = ne[i]) {
int v = e[i];
dist[v] = max(dist[v], dist[u] + w[i]);
}
// 因为不存在正环,而且题目保证都是路径>=0,所以强连通分量中必然路径长度都是0
// 即是一样一样的东西
LL res = 0;
for (int i = 1; i <= scc_cnt; i++) res += (LL)dist[i] * sz[i];
printf("%lld\n", res);
return 0;
}