POI #Year2012 #Tarjan #最短路
強聯通分量之間是不影響的,考慮對於一個強聯通分量內,方案數等於這個強聯通內的最短路\(+1\)
// Author: xiaruize
const int N = 6e2 + 10;
int n, m1, m2;
vector<int> g[N];
int dis[N][N];
bool vis[N];
int dfn[N], top[N], low[N], tot;
stack<int> st;
int res[N];
int id[N], cnt = 0;
void tarjan(int x)
{
dfn[x] = low[x] = ++tot;
st.push(x);
vis[x] = true;
for (auto v : g[x])
{
if (!dfn[v])
{
tarjan(v);
low[x] = min(low[x], low[v]);
}
else if (vis[v])
{
low[x] = min(low[x], dfn[v]);
}
}
if (dfn[x] == low[x])
{
cnt++;
while (st.top() != x)
{
id[st.top()] = cnt;
vis[st.top()] = false;
st.pop();
}
id[st.top()] = cnt;
vis[st.top()] = false;
st.pop();
}
}
void solve()
{
mms(dis, 0x3f);
cin >> n >> m1 >> m2;
rep(i, 1, m1)
{
int u, v;
cin >> u >> v;
dis[u][v] = min(dis[u][v], 1);
dis[v][u] = min(dis[v][u], -1);
g[u].push_back(v);
g[v].push_back(u);
}
rep(i, 1, m2)
{
int u, v;
cin >> u >> v;
dis[v][u] = min(dis[v][u], 0);
g[v].push_back(u);
}
rep(i, 1, n)
{
dis[i][i] = 0;
if (!dfn[i])
tarjan(i);
}
rep(k, 1, n)
{
rep(i, 1, n)
{
if (id[k] != id[i] && dis[i][k] < INF)
continue;
rep(j, 1, n)
{
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
rep(i, 1, n)
{
if (dis[i][i] < 0)
{
cout << "NIE" << endl;
return;
}
rep(j, 1, n) if (id[i] == id[j])
res[id[i]] = max(res[id[i]], dis[i][j] + 1);
}
int ans = 0;
rep(i, 1, n) ans += res[i];
cout << ans << endl;
}
#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int testcase = 1;
// cin >> testcase;
while (testcase--)
solve();
#ifndef ONLINE_JUDGE
cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
return 0;
}