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.

96 lines
2.7 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);
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];
if (a == b) {
if (w[i] > 0) { // 在同一个强连通分量中存在边权大于0的边
puts("-1"); // 必然有正环,最长路存在正环,原不等式组无解
exit(0);
}
} else
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;
}