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
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;
|
|
} |