有向グラフG =(V、E)G =(V、E)
セミコネクトと呼ばれる場合:∀u、v∈V∀u、v∈V
、u→vu→vを満たす
またはv→uv→u
、つまり、グラフ内の任意の2点u、vu、v
、ううがあります
VVへ
有向パスまたはvvから
ううへ
有向パス。G ′=(V′、E ′)G′ =(V ′、E′)の場合
满足,E′E′
EEです
合計でV′V ′
関連エッジはG′G ′と呼ばれます
GGです
エクスポートされたサブグラフの1つ。G′G ′の場合
GGです
派生サブグラフ、およびG′G ′
半接続、それはG′Gと呼ばれます
GG
半連結サブグラフ。G′G ′の場合
GGです
すべての半連結サブグラフには最大数のノードが含まれます。これはG′G ′と呼ばれます
GGです
最大の半連結サブグラフ。有向グラフGGを考える
、GGをリクエスト
最大の半連結サブグラフKKのノード数
、そして異なる最大の半連結サブグラフCCの数
。CCによる
比較的大きい場合があります。出力CCのみが必要です
XXへ
残りの。入力フォーマットの最初の行には3つの整数N、M、XN、M、Xが含まれています
サイードN、MN、M
グラフGGを表す
ポイントとエッジ、XX
上記の意味、次のMM
行、行ごとに2つの正の整数a、ba、b
、有向エッジを示す(a、b)(a、b)
。写真の各ポイントには11の番号が付けられます
NNへ
、入力で同じ(a、b)(a、b)を確認します
二度現れません。出力形式には2行が含まれている必要があります。最初の行には整数KKが含まれています
、2行目には整数C mod XC mod Xが含まれています
。データ範囲1≤N≤1051≤N≤105
、1≤M≤1061≤M≤106
、1≤X≤1081≤X≤108
入力例:6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4
出力例:3
3
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 100010, M = 2000010;
typedef long long LL;
int n, m, mod;
int h[N], hs[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
bool in_stk[N];
int id[N], scc_cnt, scc_size[N];
int f[N], g[N];
void add(int h[], int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void tarjan(int u){
dfn[u] = low[u] = ++timestamp;
stk[++ top] = u, in_stk[u] = true;
for (int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if (!dfn[j]){
tarjan(j);
low[u] = min(low[u], low[j]);
}
else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
}
if (dfn[u] == low[u]){
++ scc_cnt;
int y;
do{
y = stk[top --];
in_stk[y] = false;
id[y] = scc_cnt;
scc_size[scc_cnt] ++;
}while(y != u);
}
}
int main(){
memset(h, -1, sizeof h);
memset(hs, -1, sizeof hs);
scanf("%d%d%d", &n, &m, &mod);
while(m --){
int a, b;
scanf("%d%d", &a, &b);
add(h, a, b);
}
for (int i = 1; i <= n; i ++)
if (!dfn[i])
tarjan(i);
unordered_set<LL> S;
for (int i = 1; i <= n; i ++)
for (int j = h[i]; ~j; j = ne[j]){
int k = e[j];
int a = id[i], b = id[k];
LL hash = a * 1000000ll + b;
if (a != b && !S.count(hash)){
add(hs, a, b);
S.insert(hash);
}
}
for (int i = scc_cnt; i; i --){
if (!f[i]){
f[i] = scc_size[i];
g[i] = 1;
}
for (int j = hs[i]; ~j; j = ne[j]){
int k = e[j];
if (f[k] < f[i] + scc_size[k]){
f[k] = f[i] + scc_size[k];
g[k] = g[i];
}
else if (f[k] == f[i] + scc_size[k]) g[k] = (g[k] + g[i]) % mod;
}
}
int maxf = 0, sum = 0;
for (int i = 1; i <= scc_cnt; i ++)
if (f[i] > maxf){
maxf = f[i];
sum = g[i];
}
else if (f[i] == maxf) sum = (sum + g[i]) % mod;
cout << maxf << endl;
cout << sum << endl;
return 0;
}