【POJ1236 学校的网络】

题目大意:

  N台电脑之间能够通过有向边(u,v)从第u台电脑传输文件到第v台电脑。如果给第u台电脑投放一个文件,那么这个文件就能通过有向边传输到第v台电脑上,给你N台电脑的连接情况。那么问题来了:1、最少向这N台电脑中的几台电脑投放文件,就能使N台电脑都能接收到文件。2、最少向这N台电脑构成的图中添加几条边,使只向任何一台电脑投放文件,就能够让N台电脑接收到文件。

样例输入:

  5
  2 4 3 0
  4 5 0
  0
  0
  1 0

样例输出:

  1
  2

题解:

  首先tarjan缩点,第一问就是问有多少个入度为0的点,第二问就是问至少加多少条边使得这有向图变成一个强连通分量。

  主要问题在第二问,一个强连通分量中所有点一定有出度与入度(除法就一个点),因此缩点后的图中所有入度或者出度为0的点都要加边,每次边可以从一个出度为0的点连向入度为0的点,因为答案为min(numin,numout)

  提醒多组数据

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 struct node
 6 {
 7     int next,to;
 8 }    e[200005];
 9 int head[1005],dfn[1005],low[1005],in[1005],out[1005],vis[1005];
10 int cnt,time,s[1005],bl[1005],sc;
11 using namespace std;
12 inline void insert(int u,int v)
13 {
14     e[++cnt].next=head[u];
15     head[u]=cnt;
16     e[cnt].to=v;
17 }
18 inline void init()
19 {
20     memset(head,0,sizeof(head));
21     memset(in,0,sizeof(in));
22     memset(out,0,sizeof(out));
23     memset(low,0,sizeof(low));
24     memset(vis,0,sizeof(vis));
25     memset(dfn,0,sizeof(dfn));
26     memset(bl,0,sizeof(bl));
27     memset(s,0,sizeof(s));
28 }
29 inline void tarjan(int now)
30 {
31     dfn[now]=low[now]=++time;
32     s[++s[0]]=now,vis[now]=1;
33     for(int i=head[now];i;i=e[i].next)
34     {
35         if(!dfn[e[i].to])
36         {
37             tarjan(e[i].to);
38             low[now]=min(low[now],low[e[i].to]);
39         }
40         else    if(vis[e[i].to])
41             low[now]=min(low[now],dfn[e[i].to]);
42     }
43     if(low[now]==dfn[now])
44     {
45         bl[now]=++sc;
46         vis[now]=0;
47         while(s[s[0]]!=now)
48         {
49             bl[s[s[0]]]=sc;
50             vis[s[s[0]]]=0;
51             s[0]--;
52         }
53         s[0]--;
54     }
55 }
56 int main()
57 {
58     int n,v;
59     while(scanf("%d",&n)!=EOF)
60     {
61         init();
62         cnt=time=sc=0;
63         for(int i=1;i<=n;i++)
64             while(scanf("%d",&v) && v)
65                 insert(i,v);
66         for(int i=1;i<=n;i++)
67             if(!dfn[i])    tarjan(i);
68         for(int i=1;i<=n;i++)
69             for(int j=head[i];j;j=e[j].next)
70             {
71                 if(bl[i]!=bl[e[j].to])
72                     out[bl[i]]++,in[bl[e[j].to]]++;
73             }
74         int numin=0,numout=0;
75         for(int i=1;i<=sc;i++)
76         {
77             if(!in[i])    numin++;
78             if(!out[i])    numout++;
79         }
80         if(sc==1)    printf("1\n0\n");
81         else    printf("%d\n%d\n",numin,max(numin,numout));
82     }
83 } 

 

posted @ 2017-11-19 14:35  LittleOrange  阅读(169)  评论(0编辑  收藏  举报