Topic: Define a semi-connected diagram: Any two points in the graph can be reached in one direction. The maximum half-connected sub-graph of a graph, and the number of the maximum semi-connected sub-graphs of the graph.
Idea: Semi-connected graphs are not necessarily without rings. This test instructions me to understand.
In fact, the idea of what is not difficult to understand is not difficult to write. In order to ensure the semi-connected, so we must first deal with a diagram of the unicom situation. Using Tarjan to get the DAG, find the longest chain length on this dag is the answer to the first question. The second question can first find all f-values equal to the answer point, at which the reverse memory of the search DP.
Note In a small place, the initial value of ANS is the largest SCC size, if the 0 will be a point of WA.
CODE:
#include <set> #include <queue> #include <vector> #include <cstdio> #include <cstring># Include <iostream> #include <algorithm> #define MAXP 100010#define max 2000010using namespace std; #define Max (A, B) ((a) > (b)? (a):(b)) int points,edges,p;int head[maxp],total;int next[max],aim[max];set<pair<int,int> > G;void Add ( int X,int y) {next[++total] = head[x];aim[total] = y;head[x] = total;} int dfn[maxp],low[maxp],_clock;int stack[maxp],top;bool in_stack[maxp];int changed[maxp],scc,cnt[maxp];void Tarjan ( int x) {dfn[x] = low[x] = ++_clock;stack[++top] = x;in_stack[x] = true;for (int i = head[x]; i; i = Next[i]) {if (!dfn[aim[i] ]) Tarjan (Aim[i]), low[x] = min (Low[x],low[aim[i]), else if (In_stack[aim[i]]) low[x] = min (low[x],dfn[aim[i]]);} if (dfn[x] = = Low[x]) {int Temp;++scc;do {temp = stack[top--];in_stack[temp] = false;changed[temp] = SCC;++CNT[SCC];} while (temp! = x);}} namespace DAG {int Head[maxp],total;int next[max],aim[max];int _in[maxp];vector<int> from[maxp];int f[maxp],memory[maxp];int Ans;long long num;void Add (int x,int y) {next[++total] = Head[x];aim[tot AL] = y;head[x] = total;++_in[y];from[y].push_back (x);} int memorialsearch (int x) {if (memory[x]! =-1) return memory[x];int re = 0;for (vector<int>::iterator it = From[x].beg In (); It! = From[x].end (); ++it) if (F[*it] +:: cnt[x] = = F[x]) Re + = Memorialsearch (*it), re%= p;return memory[x] = re;} void Solve () {static queue<int> Q; memset (memory,-1,sizeof (memory)); for (int i = 1; I <=:: SCC; ++i) if (!_in[i]) {Q.push (i), f[i] =:: Cnt[i]; memory[i] = 1;} while (!q.empty ()) {int x = Q.front (), Q.pop (); for (int i = head[x]; i; i = Next[i]) {f[aim[i]] = max (F[aim[i]],f[x] +:: Cnt[aim[i]]); if (!--_in[aim[i]]) Q.push (Aim[i]); }} ans = *max_element (f + 1,f +:: SCC + 1); for (int i = 1; I <=:: SCC; ++i) if (f[i] = = ans) num = (num + memorialsearch (i))% P;}} int main () {cin >> points >> edges >> p;for (int x,y,i = 1; i <= edges; ++i) {scanf ("%d%d", &Amp;x,&y); ADD (x, y);} for (int i = 1; I <= points; ++i) if (!dfn[i]) Tarjan (i), for (int x = 1, x <= points; ++x) for (int i = head[x]; i; i = NEX T[i]) if (changed[x]! = Changed[aim[i])) if (G.find (Make_pair (changed[x],changed[aim[i])) = = = G.end ()) {Dag::add ( Changed[x],changed[aim[i]]); G.insert (Make_pair (Changed[x],changed[aim[i]));} Dag::solve (); cout << Dag::ans << ' \ n ' << dag::num << endl;return 0;}
Bzoj 1093 Zjoi 2007 Maximum semi-connected sub-graph strong Unicom component + topology map DP