有向グラフの強く接続されたコンポーネント----最大半接続サブグラフ

有向グラフ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;
}
164のオリジナル記事が公開されました いいね112 訪問者6756

おすすめ

転載: blog.csdn.net/qq_45772483/article/details/105607141