今天終于第一次寫了強連通分量的題目

雖然以前老早就知道有這么個東西,對這個東西也有概念,但是確實從來沒有寫過判別的算法

原來如此簡單,但是確實也很巧妙。

在算法導(dǎo)論上面看到的K算法,方法就是做兩遍DFS,因為強連通分量有一個性質(zhì),就是如果把所有的邊反向,那么它仍然是一個強連通分量。

但是今天我用的是Tarjan算法,據(jù)說效率比K算法高很多,事實上也應(yīng)該是這樣,因為Tarjan算法只做了一次DFS

其實思想也很簡單,就是一直DFS(u),向下向下向下,如果突然發(fā)現(xiàn)有一個點可以回到u了,那么這個肯定是一個強連通分量。

哈哈,是不是很通俗。

嚴格的定義過程大家可以看這里http://www.cmykrgb123.cn/blog/scc-tarjan/

我也是參考了這個才做出來的Tarjan算法,Wiki上的那個過于龐大了,雖然封裝的非常好

說說本題,其實就是找強連通分量,然后把每個強連通分量當(dāng)成一個“超點”來考慮

如果這個“超點”的入度為零,那么它就必然是一個源頭,統(tǒng)計這樣的“超點”的個數(shù),就是第一問的答案。

第二問,如果有一個“超點”入度不是0,但是出度是0,那就說明這個“超點”可以給其他“超點”作貢獻。

我們就找這樣的點對,把入度是0和出度是0的點連起來。

這樣匹配過后,剩下的要么全是入度是0的,要么全是出度是0的,這些就沒辦法了,隨便從一個連通分量連接過來一條邊就可以了。

所以第二問的答案就是所有的“超點”中,入度是0和出度是0的點大的那個數(shù)。

  1 import java.io.*;
  2 import java.util.*;
  3 /*
  4 ID: yanglei4
  5 LANG: JAVA
  6 TASK:schlnet
  7 */
  8 public class schlnet {
  9     boolean[] inStack;
 10     int[] DFN;
 11     int[] LOW;
 12     int index = 0;
 13     int[] Stack;
 14     int top = 0;
 15     int[][] map;
 16     int BelongCount = 0;
 17     int[] belong;
 18     
 19     public void Tarjan(int i) {
 20         DFN[i] = LOW[i] = ++index;
 21         inStack[i] = true;
 22         Stack[top++= i;
 23         for (int j = 1; j <= map[i][0]; j++) {
 24             if (DFN[map[i][j]] == 0) {
 25                 Tarjan(map[i][j]);
 26                 if (LOW[map[i][j]] < LOW[i])
 27                     LOW[i] = LOW[map[i][j]];
 28             }
 29             else if (inStack[map[i][j]] && DFN[map[i][j]] < LOW[i])
 30                 LOW[i] = DFN[map[i][j]];
 31         }
 32         if (DFN[i] == LOW[i]) {
 33             int j = 0;
 34             do {
 35                 j = Stack[--top];
 36                 inStack[j] = false;
 37                 belong[j] = BelongCount;
 38             } while (j != i);
 39             BelongCount++;
 40         }
 41         
 42     }
 43     
 44     public void done() throws IOException {
 45         BufferedReader f = new BufferedReader(new FileReader("schlnet.in"));
 46         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("schlnet.out")));
 47         int N = Integer.parseInt(f.readLine());
 48         map = new int[N + 1][N + 1];
 49         DFN = new int[N + 1];
 50         LOW = new int[N + 1];
 51         inStack = new boolean[N + 1];
 52         Stack = new int[N + 1];
 53         belong = new int[N + 1];
 54         
 55         Arrays.fill(belong,-1);
 56         for (int i = 1; i <= N; i++) {
 57             StringTokenizer st = new StringTokenizer(f.readLine());
 58             int len = st.countTokens();
 59             map[i][0= len - 1;
 60             for (int j = 1; j <= len - 1; j++)
 61                 map[i][j] = Integer.parseInt(st.nextToken());    
 62         }
 63         
 64         for (int i = 1; i <= N; i++) {
 65             if (DFN[i] == 0)
 66                 Tarjan(i);
 67         }    
 68         boolean[][] dis = new boolean[BelongCount + 1][BelongCount + 1];
 69         for (int i = 1;i <= N;i++) {
 70             for (int k = 1;k <= map[i][0];k++)
 71                 dis[belong[i] + 1][belong[map[i][k]] + 1= true;
 72         }
 73         int[] oud = new int[BelongCount + 1];
 74         int[] ind = new int[BelongCount + 1];
 75         
 76         for (int i = 1;i <= BelongCount;i++) {
 77             for (int j = 1; j<= BelongCount;j++) {
 78                 if (i!=&& dis[i][j]) {
 79                     oud[i]++;
 80                     ind[j]++;
 81                 }
 82             }
 83         }
 84         
 85         int i0 = 0;
 86         int o0 = 0;
 87         for (int i = 1;i <= BelongCount;i++) {
 88             if (ind[i] == 0)
 89                 i0++;
 90             if (oud[i] == 0)
 91                 o0++;
 92         }
 93         
 94         if (BelongCount == 1) {
 95             out.println("1");
 96             out.println("0");
 97         }
 98         else {
 99             out.println(i0);
100             out.println(i0>o0?i0:o0);
101         }    
102         out.close();    
103     }
104 
105     public static void main(String[] args) throws IOException {
106         schlnet t = new schlnet();
107         t.done();
108         System.exit(0);
109     }
110 }
111