一道差分约束的好体。
- 限制条件 1 ((A) 的成绩正好比 (B) 快 1 秒)
(dis[a][b]=1),(dis[b][a]=−1)。(双向边适用于定量比较)
- 限制条件 2 ((C) 的成绩不比 (D) 的差)
(dis[b][a] = 0) (单向边适用于定性比较)
要求最多能拿到的成绩种数;
因为图存的是两点的最大差值,所以对于图中的强联通分量来说,任意两点的差值是确定的,所以在强联通分量中求出一条最长的两点之间的最短路 + 1,就是这个强联通分量中的答案
统计完强联通分量的答案之后,对图进行缩点,因为条件一可以成自环,所以剩下的图是 0 边连接各强联通分量,所以每个强联通分量之间都是大于等于关系,所以可以无限的扩大,这些边就可以忽略了;
然后直接单独统计每个强联通分量的答案求和就好了
code
/*
work by:Ariel_
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;
const int N = 610;
int read(){
int x = 0,f = 1; char c = getchar();
while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
return x*f;
}
int n, m1, m2, dis[N][N], dfn[N], id[N], tot, vis[N], low[N], cnt, val[N], k;
stack<int> s;
bool opt;
void tarjan(int x) {
dfn[x] = low[x] = ++tot, vis[x] = 1;
s.push(x);
for (int i = 1; i <= n; i++) {
if(dis[x][i] <= 1) {
if(!dfn[i]) {
tarjan(i);
low[x] = min(low[x], low[i]);
}
else if(vis[i]) low[x] = min(dfn[i], low[x]);
}
}
if(low[x] == dfn[x]) {
do{
k = s.top(), s.pop();
vis[k] = 0, id[k] = x;
}while(k != x);
}
}
int main(){
n = read(), m1 = read(), m2 = read();
memset(dis, 0x3f3f3f3f, sizeof dis);
for (int i = 1, a, b; i <= m1; i++) {
a = read(), b = read();
dis[a][b] = min(dis[a][b], 1);
dis[b][a] = min(dis[b][a], -1);
}
for (int i = 1, a, b; i <= m2; i++) {
a = read(), b = read();
dis[b][a] = min(dis[b][a], 0);
}
for (int i = 1; i <= n; i++) dis[i][i] = 0;
for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i);
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
if (id[i] != id[k] || dis[i][k] == 0x3f3f3f3f) continue;
for (int j = 1; j <= n; j++) {
if (id[i] != id[j]) continue;
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
for (int i = 1; i <= n; i++) {
if (dis[i][i] < 0) {opt = 1; break;}
for (int j = 1; j <= n; j++) if (id[i] == id[j]) val[id[i]] = max(val[id[i]], dis[i][j] + 1);
}
if (opt) printf("NIE");
else {
int Ans = 0;
for (int i = 1; i <= n; i++) Ans += val[i];
printf("%d", Ans);
}
puts("");
return 0;
}