半連通子圖定義:誘導子圖中任意兩點 u, v,至少有一條方向路徑連通 (u→v 或 v→u)。等價於:縮點後的 DAG 中,節點構成一條**鏈** (任意兩點可達)。故問題轉為:**在縮點後的 DAG 中找最長路徑 (點權為強連通分量大小) 及其方案數**。
set 或排序唯一化)。len[u] = 以 u 為起點的最大權重和。ways[u] = 對應方案數 (模 p)。len[u] = max(len[u], len[v] + size[u]),v 為 u 的出邊鄰居。len 及對應 ways 總和。void Tarjan(int x) {
dfn[x] = low[x] = ++timer;
stk[++top] = x; inStack[x] = true;
for (int e = head[x]; e; e = nxt[e]) {
int y = to[e];
if (inStack[y]) low[x] = min(low[x], dfn[y]);
else if (!dfn[y]) { Tarjan(y); low[x] = min(low[x], low[y]); }
}
if (dfn[x] == low[x]) {
++sccCnt;
do { int y = stk[top--]; inStack[y] = false; belong[y] = sccCnt; size[sccCnt]++; } while (y != x);
}
}
for (int u = sccCnt; u >= 1; --u) { // 假設節點編號即拓撲逆序
len[u] = size[u]; ways[u] = 1;
for (int e = head[u]; e; e = nxt[e]) {
int v = to[e];
if (len[v] + size[u] > len[u]) { len[u] = len[v] + size[u]; ways[u] = 0; }
if (len[v] + size[u] == len[u]) ways[u] = (ways[u] + ways[v]) % mod;
}
// 更新全域答案
}
u->v,縮點後 belong[u] -> belong[v] (若不同 SCC)。% mod。