/* Don't say it's a lot of water or something ... I just want to remember the kosaraju of this kind of cock-bombing. The DFS Sequence extension algorithm (which might be added to my YGYLCA) */
Test Instructions God horse do not say, OK, is to give you a map, n points, and then n line each line describes the point of the out side, the diagram is finished, and then shrink points, and then ask how many points do not enter the degree, and then asked to add a few sides can make the diagram stronger Unicom diagram.
Strong Unicom diagram: The figure of any two points can be reached between each other (the premise is that there is a map you understand, the map is a bit messy, do not algorithm, the mob search is good)
Strong Unicom components: the same strong unicom map, but a part of the picture.
To take a component as a point, and to shrink (generally not, to record each point in the first few strong unicom components).
Kosaraju algorithm: This is India native also, algorithm name of very dick! Algorithm: To search again, when out of the side are running the record of its dfn[x]=++cnt, and then reverse the building (generally at the beginning of the building), and then according to the DFN sequence n-->1 on the reverse graph run DFS, can sweep and not be assigned (unassigned component ordinal) of the point is a strong unicom component.
(All kinds of "unicom" "Connected" I don't care, don't spit groove, it seems to be connected? )
Two kinds of code :
One is the adjacency matrix, that is, to save a bool MAP[MAXN][MAXN] means can pass, and then do not have to build the inverse diagram.
The other is the adjacency table (chain forward star), need to build a reverse graph, and this problem may be a dense map, so it is not recommended.
of course, I submitted more than 10 times the code, measured the maximum number of 2477 Edge, you can refer to it when using adjacency table.
Do not worry about the code, first write my understanding of the Kosaraju proof, of course, may be a little less rigorous, not willing to see the blog, write as if very good (I am looking a bit blindfolded (impatient, although very short)):
http://blog.csdn.net/dm_vincent/article/details/8554244
OK, here's my proof :
Let's start with the meanings of various variables:
struct KSD
{
int v,next;
}ea[m],eb[m];/*, Inverse diagram */
int Heada[n],headb[n],num,n;/*head Array Don't say */
int DFN[N],CNT;/*DFN can refer to code */
int id[n],group;/*id[i],i in the first few strong unicom components */
int rd[n],od[n];/* in degrees */
BOOL visit[n];/* Whether or not Dfs was swept over the map */
First we are on the inverse of the DFS, sweep to the same component, that is, at sweep I point, all can to I point and unassigned ID point (including I point) is a strong unicom component, we from here to testify.
If the point A and I are strong, then you can be sure if B point and I point strong unicom, then A and b strong unicom it? It's a good understanding, water. Then we only have a strong link to each point in this weight and I point.
Strong unicom: A can go to I,i can also to a.
Since can sweep, then can be sure a can to I, no objection? There are objections to the thought of no objection to look down. Now we just need to prove I can get to a!
0 if Dfn[a]>dfn[i], then a must have an ID value, right? Then there must be no more i->a. So at this point we can all be poor.
First we actually built a search tree in DFS, we can give two cases, ①a in the subtree of I. ②a is not in the subtree of I.
Say ① first. This I must be able to search for a. (A is by I search the past!) )
again ②, two cases: ②-① if I in a subtree, did not sweep I to I to assign the ID value, a is definitely not assigned ID value, right? Then the contradiction in the 0 line , then there is ②-②i must not be in a subtree inside. So it can be divided into two kinds of situations.
②-②-① in their LCA, sweep to the I branch first. ②-②-② sweep to a branch first.
First say ②-②-①: Since sweep to I branch, then if I can to a, then because sweep to I when a must have not been swept, so can from I to sweep a, then the front of the proposition "②-②" contradiction, because at this time a unexpectedly became I ancestors?!! The proposition is false.
Again ②-②-②: With ②-②-①, from I can not sweep to a, otherwise contradictory to "②", so I can not to a.
Quit,to②-② (because both propositions are false), so Quit,to②,② is false again.
So you can be sure only a in the I subtree inside, can make strong Unicom component set up!
The proof!
Codes
Adjacency Matrix:
#include <cstdio> #include <cstring> #include <algorithm> #define N 105using namespace std;// Kosaruju algorithm! int n;int dfn[n],cnt;int id[n],group;int rd[n],od[n];bool map[n][n],visit[n];int ans1,ans2;void init () {cnt=group=0; Ans1=ans2=0;memset (map,0,sizeof (map)), memset (visit,0,sizeof (visit)); memset (id,0,sizeof (ID)); memset (rd,0,sizeof (RD)); memset (od,0,sizeof (OD));} void Dfs (int x) {visit[x]=1;for (int i=1;i<=n;i++) if (Map[x][i]&&!visit[i]) DFS (i);d Fn[++cnt]=x;return;} void dfst (int x) {id[x]=group;for (int i=1;i<=n;i++) if (Map[i][x]&&!id[i]) dfst (i); return;} void Kosaruju () {int i,j,v;for (i=1;i<=n;i++) if (!visit[i]) DFS (i); for (i=n;i;i--) {v=dfn[i];if (!id[v]) {group++; Dfst (v);}} return;} void handle () {int i,j,u,v;for (i=1;i<=n;i++) {for (j=1;j<=n;j++) {u=id[i];v=id[j];if (map[i][j]&&u!=v) { od[u]++;rd[v]++;}}} for (i=1;i<=group;i++) {if (!rd[i]) ans1++;if (!od[i]) ans2++;} /*if (group==1) ans2=0, plus this sentence without any use of nonsense can be 0ms (do not forget to delete the comments) I guess the compile time has some unknown impact, and thus affect the evaluation of the timing. Run Id:poj 13468874*/printf ("%d\n", ans1), if (group==1) puts ("0"), Else printf ("%d\n", Max (ANS1,ANS2));} int main () {//freopen ("test.in", "R", stdin), int i,a;while (scanf ("%d", &n)!=eof) {init (); for (i=1;i<=n;i++) while (scanf ("%d", &a), a) Map[i][a]=1;kosaruju (); handle ();} return 0;}
adjacency table (Chain forward star):
#include <cstdio> #include <cstring> #include <algorithm> #define N 105#define M 2477/* limit data 2,477 edges, But the normal should open 10010 (even because it did not say there is no heavy side, but also should be open bigger!) ) */using namespace Std;//kosaruju algorithm! struct Ksd{int v,next;} Ea[m],eb[m];int heada[n],headb[n],num,n;int dfn[n],cnt;int id[n],group;int rd[n],od[n];bool visit[N];int ans1,ans2; void Add (int u,int v) {++num;ea[num].v=v;eb[num].v=u;ea[num].next=heada[u];eb[num].next=headb[v];heada[u]=headb[v] =num;} void Init () {Ans1=ans2=0;num=cnt=group=0;memset (id,0,sizeof (ID)); memset (rd,0,sizeof (RD)); memset (od,0,sizeof (OD)) ; memset (Heada,0,sizeof (Heada)); Memset (Headb,0,sizeof (HEADB)); memset (visit,0,sizeof (visit));} void Dfs (int x) {int i,v;visit[x]=1;for (i=heada[x];i;i=ea[i].next) {v=ea[i].v;if (!visit[v]) Dfs (v);} Dfn[++cnt]=x;} void dfst (int x) {int i,v;id[x]=group;for (i=headb[x];i;i=eb[i].next) {v=eb[i].v;if (!id[v]) dfst (v);}} void Kosaruju () {int i,j,v;for (i=1;i<=n;i++) if (!visit[i]) DFS (i); for (i=n;i;i--) {v=dfn[i];if (!id[v]) {group++; Dfst (v);}} return;} void handle () {int i,j,u,V;for (i=1;i<=n;i++) {u=id[i];for (j=heada[i];j;j=ea[j].next) {v=id[ea[j].v];if (u!=v) {od[u]++;rd[v]++;}}} for (i=1;i<=group;i++) {if (!rd[i]) ans1++;if (!od[i]) ans2++;} /*if (group==1) ans2=0, plus this sentence without any use of nonsense can be 0ms (do not forget to delete the comments) I guess the compile time has some unknown impact, and thus affect the evaluation of the timing. Run Id:poj 13468874*/printf ("%d\n", ans1), if (group==1) puts ("0"), Else printf ("%d\n", Max (ANS1,ANS2));} int main () {//freopen ("test.in", "R", stdin), int i,a;while (scanf ("%d", &n)!=eof) {init (); for (i=1;i<=n;i++) while (scanf ("%d", &a), a) Add (i,a); Kosaruju (); handle ();} return 0;}
Copy to Google TranslateTranslation ResultsCode:
"POJ1236" Network of Schools strong connectivity (this article Kosaraju)