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.

76 lines
2.2 KiB

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010, M = 300010;
//与AcWing 1169. 糖果 这道题一模一样,连测试用例都一样
stack<int> q; //有时候换成栈判断环很快就能
LL dist[N];
bool st[N];
int cnt[N];
int n, m; //表示点数和边数
//邻接表
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
bool spfa() { //求最长路,所以判断正环
memset(dist, -0x3f, sizeof dist); //初始化为-0x3f
//差分约束从超级源点出发
dist[0] = 0;
q.push(0);
st[0] = true;
while (q.size()) {
int u = q.top();
q.pop();
st[u] = false;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] < dist[u] + w[i]) { //求最长路
dist[j] = dist[u] + w[i];
cnt[j] = cnt[u] + 1;
//注意多加了超级源点到各各节点的边
if (cnt[j] >= n + 1) return false;
if (!st[j]) {
q.push(j);
st[j] = true;
}
}
}
}
return true;
}
int main() {
memset(h, -1, sizeof h);
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++) {
int op, a, b; // op为选择
scanf("%d %d %d", &op, &a, &b);
if (op == 1) /** a == b => (a >= b , b >= a) */
add(a, b, 0), add(b, a, 0);
else if (op == 2) /** b >= a + 1 */
add(a, b, 1);
else if (op == 3) /** a >= b */
add(b, a, 0);
else if (op == 4) /** a >= b + 1 */
add(b, a, 1);
else /** b >= a */
add(a, b, 0);
}
/** xi >= x0 + 1 (每个小朋友都要至少一个糖果)*/
//将所有节点与超级源点x0相连
for (int i = 1; i <= n; ++i) add(0, i, 1);
if (!spfa())
puts("-1");
else {
LL res = 0;
for (int i = 1; i <= n; ++i) res += dist[i];
printf("%lld\n", res);
}
return 0;
}