强联通块tarjan算法


http://poj.org/problem?id=1236
第一问:需要几个学校存在软件,才能通过传递,使得所有的学校都有软件
用tarjan算法求出强联通分量后,将每个联通分量缩成一个点,那么问题1的答案就是入度为0的点的个数
为什么?入度为0的点,肯定不能通过其他学校传送软件给他,所以他必须存在一份软件
第二问:需要加几条边,才能使得图强联通
缩点后,a为所有入度为0的点的个数,b为所有出度为0的点的个数,那么答案就是max(a,b)

 

 1 #include <stdio.h>

 2 #include <string.h>

 3 #include <vector>

 4 #include <stack>

 5 using namespace std;

 6 const int N = 100 + 10;

 7 vector<int> G[N];

 8 stack<int> st;

 9 bool vis[N];

10 int sccno[N],pre[N],lowlink[N],in[N],out[N],dfs_clock,scc_cnt;

11 int min(const int &a, const int &b)

12 {

13     return a < b ? a : b;

14 }

15 void tarjan(int u)

16 {

17     pre[u] = lowlink[u] = ++dfs_clock;

18     st.push(u);

19     for(int i=0; i<G[u].size(); ++i)

20     {

21         int v = G[u][i];

22         if(!pre[v])

23         {

24             tarjan(v);

25             lowlink[u] = min(lowlink[u],lowlink[v]);

26         }

27         else if(!sccno[v])

28             lowlink[u] = min(lowlink[u],pre[v]);

29     }

30     if(lowlink[u]==pre[u])

31     {

32         scc_cnt++;

33         for(;;)

34         {

35             int x = st.top();st.pop();

36             sccno[x] = scc_cnt;

37             if(x==u) break;

38         }

39     }

40 }

41 void find_scc(int n)

42 {

43     for(int i=1; i<=n; ++i)

44         if(!pre[i])

45             tarjan(i);

46 }

47 int main()

48 {

49     int n,i,a,b;

50     scanf("%d",&n);

51     for(a=1; a<=n; ++a)

52     {

53         while(scanf("%d",&b),b)

54         {

55             G[a].push_back(b);

56             vis[b] = true;

57         }    

58     }

59     find_scc(n);

60     for(i=1; i<=scc_cnt; ++i) in[i] = out[i] = 1;

61     for(int u=1; u<=n; ++u)

62         for(i=0; i<G[u].size();++i)

63         {

64             int v = G[u][i];

65             if(sccno[u] != sccno[v]) in[sccno[v]] = out[sccno[u]] = 0;

66         }

67     a = b = 0;

68     for(i=1; i<=scc_cnt; ++i)

69     {

70         if(in[i]) a++;

71         if(out[i]) b++;

72     }    

73     int ans = a > b ? a : b;

74     if(scc_cnt == 1) ans = 0;

75     printf("%d\n%d\n",a,ans);

76     return 0;

77 }

 

你可能感兴趣的:(tar)