zoukankan      html  css  js  c++  java
  • P2746 [USACO5.3]校园网Network of Schools [tarjan缩点]

    题目描述

    一些学校连入一个电脑网络。那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”)。注意即使 BB 在 AA 学校的分发列表中,AA 也不一定在 BB 学校的列表中。

    你要写一个程序计算,根据协议,为了让网络中所有的学校都用上新软件,必须接受新软件副本的最少学校数目(子任务 A)。更进一步,我们想要确定通过给任意一个学校发送新软件,这个软件就会分发到网络中的所有学校。为了完成这个任务,我们可能必须扩展接收学校列表,使其加入新成员。计算最少需要增加几个扩展,使得不论我们给哪个学校发送新软件,它都会到达其余所有的学校(子任务 B)。一个扩展就是在一个学校的接收学校列表中引入一个新成员。

    输入格式

    输入文件的第一行包括一个正整数 NN,表示网络中的学校数目。学校用前 NN 个正整数标识。

    接下来 NN 行中每行都表示一个接收学校列表(分发列表),第 i+1i+1 行包括学校 ii 的接收学校的标识符。每个列表用 00 结束,空列表只用一个 00 表示。

    输出格式

    你的程序应该在输出文件中输出两行。

    第一行应该包括一个正整数,表示子任务 A 的解。

    第二行应该包括一个非负整数,表示子任务 B 的解。

    输入输出样例

    输入 #1
    5
    2 4 3 0
    4 5 0
    0
    0
    1 0
    输出 #1
    1
    2

    说明/提示

    2 le N le 1002N100。

    题目翻译来自NOCOW。

    USACO Training Section 5.3

    思路

      由题意:

      第一问: 显然对于每个学校能到达的点都应该染成用一种颜色, 换句话说, 就是求多少个入度为 0 的学校.

      第二问: 至少连几条边使得全部的点强连通, 换句话说, 要使得所有点出入度都不为0.

      因为有环的存在, 可以考虑直接缩点, 然后统计各强连通块的出入度, 为了使所有点出入度不为0, 只需取入度为0和出度为0的最大值即可.

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 
      4 using namespace std;
      5 typedef long long LL;
      6 const int maxn = 1e5 + 7;
      7 
      8 int head[maxn], dfn[maxn], low[maxn], st[maxn];
      9 int cnt = 0, tot = 0, tim = 0, top = 1, n, cl = 0;
     10 int vis[maxn];
     11 int color[maxn];
     12 int ans[maxn];
     13 int nxt[maxn];
     14 int circle_size[maxn];
     15 int cas[maxn][5];
     16 int in[maxn];
     17 int out[maxn];
     18 
     19 /*
     20 head[],结构体edge:存边
     21 
     22 dfn[],low[]:tarjan中数组
     23 
     24 st[]:模拟栈
     25 
     26 out[]:出边
     27 
     28 sd[]:强连通分量存储
     29 
     30 dq[]:统计答案
     31 */
     32 
     33 template<class T>inline void read(T &res)
     34 {
     35     char c;T flag=1;
     36     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     37     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     38 }
     39 
     40 struct Edge{
     41     int nxt, to;
     42 }edge[maxn * 2];
     43 
     44 inline void BuildGraph(int from, int to)
     45 {
     46     cnt++;
     47     edge[cnt].to = to;
     48     edge[cnt].nxt = head[from];
     49     head[from] = cnt;
     50 }
     51 
     52 void tarjan(int x)
     53 {
     54     tim++;
     55     dfn[x] = low[x] = tim;
     56     st[top] = x;
     57     top++;
     58     vis[x] = 1;
     59     for(int i = head[x] ; i != 0; i = edge[i].nxt)
     60     {
     61         int u = edge[i].to;
     62         if(vis[u] == 0)
     63         {
     64             tarjan(u);
     65             low[x] = min(low[x],low[u]);
     66         }
     67         else if(vis[u] == 1)
     68                 low[x] = min(low[x],dfn[u]);
     69     }
     70     if(dfn[x] == low[x])
     71     {
     72         cl++;
     73         do
     74         {
     75             top--;
     76             color[st[top]] = cl;
     77             vis[st[top]] = -1;
     78         }while( st[top] != x );
     79     }
     80     return ;
     81 }
     82 
     83 int main()
     84 {
     85     scanf("%d",&n);
     86     int q = 1;
     87     for ( int i = 1; i <= n; ++i ) {
     88         int x;
     89         while(scanf("%d",&x) && x) {
     90             BuildGraph(i, x);
     91             cas[q][1] = i, cas[q][2] = x;
     92             q++;
     93         }
     94     }
     95     cl = 0;
     96     memset(color, 0, sizeof(color));
     97     memset(vis, 0, sizeof(vis));
     98     for ( int i = 1; i <= n; ++i ) {
     99         if( !vis[i] ) {
    100             tarjan(i);
    101         }
    102     }
    103     for ( int i = 1; i < q; ++i ) {
    104         if(color[cas[i][1]] != color[cas[i][2]]) {
    105             out[color[cas[i][1]]]++;
    106             in[color[cas[i][2]]]++;
    107         }
    108     }
    109     int num_in = 0, num_out = 0;
    110     for ( int i = 1; i <= cl; ++i ) {
    111         if(in[i] == 0) {
    112             num_in++;
    113         }
    114         if(out[i] == 0) {
    115             num_out++;
    116         }
    117     }
    118     if(cl == 1) {
    119         puts("1
    0");
    120     }
    121     else 
    122         printf("%d
    %d
    ",num_in, max(num_in, num_out));
    123     return 0;
    124 }
    View Code
  • 相关阅读:
    庆贺自己的软件入围中国软件创新大赛,可惜精英奖没有评上。一个笔记本飞了,哈哈,大奖500万呢!
    VMware vSphere开发(2)配置VMware vSphere Web Services SDK的开发环境
    IPhone 视图切换的的2种方法
    Windows系统加固方案
    我们公司原来C++招聘考试题,题目难度正常,没有稀奇古怪的题,如果答对60分以上,恭喜你基本算一个合格的网络开发工程师了。
    算法分析整数划分
    Java反射机制
    Java类集
    设计包含min函数的栈
    ASP.NET学习之Membership
  • 原文地址:https://www.cnblogs.com/orangeko/p/12377943.html
Copyright © 2011-2022 走看看