// 题意:详细题意省略,要点是求所有人有多少种不同的取值
// 思路:差分约束最短路只能够求满足答案的最大解和最小解,但是对于取值却无法求解
// 可以发现,在一个强量通分量内,从任意点可以到达其他点,也就是说对于两个点,他们一定有一个 A+W1>=B 与 B+W2>=A 的双向限制, 即 W2 >=A-B>= -W1
// 又因为我们的边权只有1,-1,0 所以说我们找到 A-B 的最大差值即是一个scc的贡献
// 但是对于不同的SCC之间只有一个单项边,假设有两个scc A和B, 也就是只有一个单项限制 A-B<=W1 即 B-A>=W1
// 所以对于两个不同SCC我们可以取值使他们之间的贡献没有交集
// 所以最后的答案是所有scc的贡献之和
//
// 另外这题要求A-B最大差值,也就是说我要求多源最短路,当然我用单源最短路求出来后 dis[a]-dis[b]也行
// 但是我们也可以直接用floyd,因为这题是个稀疏图(注意数据,这题n只有700,m达到了)
// 同时floyd判负环的方式可以看一下!!!!!!!!!
//
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m1, m2;
struct edge {
int nxt, to, wt;
}tr[2 * N];
int head[N], cnt, dis[700][700], vis[700];
void add(int a, int b, int w) {
tr[++cnt].to = b;
tr[cnt].wt = w;
tr[cnt].nxt = head[a];
head[a] = cnt;
}
int main() {
memset(dis, 0x3f, sizeof(dis));
cin >> n >> m1 >> m2;
for (int i = 1; i <= n; i++) dis[i][i] = 0;
int a, b;
for (int i = 1; i <= m1; i++) {
cin >> a >> b;
dis[a][b] = min(dis[a][b], 1);
dis[b][a] = min(dis[b][a], -1);
}
for (int i = 1; i <= m2; i++) {
cin >> a >> b;
dis[b][a] = min(dis[b][a],0);
}
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = min(dis[i][k] + dis[k][j], dis[i][j]);
for (int i = 1; i <= n; i++) {
if (dis[i][i] < 0) {
cout << "NIE" << endl;
return 0;
}//判负环
}
int ans = 0;
for(int i=1; i<=n; i++)
if (!vis[i]) {
vector<int> v;
for(int j=1; j<=n; j++)
if (dis[j][i] <= n && dis[i][j] <= n) {
v.push_back(j);
vis[j] = true;
}
int d = 0;
for (auto p : v)
for (auto q : v)
d = max(d, dis[p][q]);
ans += d + 1;
v.clear();
}//dls的不用tarjan写法
cout << ans << endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m1, m2;
struct edge {
int nxt, to, wt;
}tr[2 * N];
int head[N], cnt, dis[700][700], ans[700];
void add(int a, int b, int w) {
tr[++cnt].to = b;
tr[cnt].wt = w;
tr[cnt].nxt = head[a];
head[a] = cnt;
}
int dfn[N], low[N], idx, ins[N], ct, bel[N];
stack<int> stk;
vector<int> scc[700];
void dfs(int u) {
dfn[u] = low[u] = ++idx;
ins[u] = true;
stk.push(u);
for (int y = head[u]; y; y = tr[y].nxt) {
int v = tr[y].to;
if (!dfn[v]) dfs(v);
if (ins[v]) low[u] = min(low[u], low[v]);
}
if (dfn[u] == low[u]) {
++ct;
while (true) {
int v = stk.top();
scc[ct].push_back(v);
ins[v] = false;
bel[v] = ct;
stk.pop();
if (u == v) break;
}
}
}
int main() {
memset(dis, 0x3f, sizeof(dis));
memset(ans, -1, sizeof(ans));
cin >> n >> m1 >> m2;
for (int i = 1; i <= n; i++) dis[i][i] = 0;
int a, b;
for (int i = 1; i <= m1; i++) {
cin >> a >> b;
add(b, a, -1); add(a, b, 1);
dis[a][b] = min(dis[a][b], 1);
dis[b][a] = min(dis[b][a], -1);
}
for (int i = 1; i <= m2; i++) {
cin >> a >> b;
add(b, a, 0);
dis[b][a] = min(dis[b][a], 0);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) dfs(i);
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
if (bel[i] == bel[k])
for (int j = 1; j <= n; j++)
if (bel[i] == bel[j])
dis[i][j] = min(dis[i][k] + dis[k][j], dis[i][j]);
for (int i = 1; i <= n; i++) {
if (dis[i][i] < 0) {
cout << "NIE" << endl;
return 0;
}//判负环
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (bel[i] == bel[j] && dis[i][j] <= n)//非常的关键,假如说在同一个强联通分量内 dis[i][j] 是被正常更新的,但 dis[j][i] 却不行,因为很可能只存在一条从i到j的单路
ans[bel[j]] = max(ans[bel[j]], dis[i][j]);
int tot = 0;
for (int i = 1; i <= ct; i++) tot += ans[i];
tot += ct;
cout << tot << endl;
return 0;
}