POJ 1236(强连通分量)Tarjan+缩点

以前写过这个题,因为还就不写tarjan了,用这道题熟悉一下。

题目大意:
  给定一个n (n<=100)个点的有向图,问:
  Q1、最少需要选择多少个点,使得从这些点出发能遍历完整个图;
  Q2、最少需要添加多少条有向边,使得整个图成为连通图;
分析:
        开始Q1我想复杂了,先说Q2吧,和hdu2767一样,当时我自己ac了hdu2767,可是做Q2的时候又一下没想到,便找出了原来的代码……
        先由Tarjan算法求出强连通分量后进行缩点,得到每个强连通分量的入度in[],出度out[];
  Q1: 入度为0的强连通分量个数; 
  Q2: max(  入度为0的强连通分量个数 ,  出度为0的强连通分量个数  );
//题解 转自某神牛blog,忘了。。。代码自己的。
 
View Code
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #define M 100100
 6 #define N 5000
 7 using namespace std;
 8 int n,m,cnt,t,divg,belong[N],head[M],next[M],to[M],dfn[N],low[N],in[N],out[N],p,stack[N],innum,outnum;
 9 bool vis[N],fg[N];
10 inline void add(int u,int v) 
11 {
12     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
13 }
14 void read()
15 {
16     memset(vis,0,sizeof vis);
17     memset(dfn,0,sizeof dfn);
18     memset(in,0,sizeof in);
19     memset(out,0,sizeof out);
20     memset(head,-1,sizeof head);cnt=0;
21     divg=0; p=0; t=0;//时间标志 
22     scanf("%d",&n);
23     for(int i=1,a;i<=n;i++)
24         while(scanf("%d",&a),a) add(i,a);
25 }
26 void dfs(int u)
27 {
28     t++;
29     dfn[u]=low[u]=t;
30     stack[++p]=u; fg[u]=true;
31     for(int i=head[u];~i;i=next[i])
32     {
33         if(!dfn[to[i]])
34         {
35             dfs(to[i]);
36             low[u]=min(low[u],low[to[i]]);
37         }
38         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
39     }
40     if(dfn[u]==low[u])
41     {
42         divg++;
43         int tmp=-1;
44         while(tmp!=u)
45         {
46             tmp=stack[p--];
47             belong[tmp]=divg;
48             fg[tmp]=false;
49         }
50     }
51 }
52 void go()
53 {
54     for(int i=1;i<=n;i++)
55         if(!dfn[i]) dfs(i);
56     for(int i=1;i<=n;i++)
57         for(int j=head[i];~j;j=next[j])
58             if(belong[i]!=belong[to[j]])
59                 out[belong[i]]++,in[belong[to[j]]]++;
60     innum=outnum=0;
61     for(int i=1;i<=divg;i++)
62     {
63         if(!in[i]) innum++;
64         if(!out[i]) outnum++;
65     }
66     printf("%d\n",innum);
67     if(divg==1) printf("0\n");
68     else printf("%d\n",max(innum,outnum));
69 }
70 int main()
71 {
72     read();
73     go();
74     system("pause");
75     return 0;
76 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2662537.html