码迷,mamicode.com
首页 > Web开发 > 详细

P2746 [USACO5.3]校园网Network of Schools 强连通

时间:2019-05-02 11:22:21      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:发送   nbsp   void   input   电脑   分发   lap   back   %s   

  

题目描述

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

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

输入输出格式

输入格式:

 

输入文件的第一行包括一个整数 N:网络中的学校数目(2 <= N <= 100)。学校用前 N 个正整数标识。

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

 

输出格式:

 

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

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

第二行应该包括子任务 B 的解。

 

输入输出样例

输入样例#1: 复制
5
2 4 3 0
4 5 0
0
0
1 0
输出样例#1: 复制
1
2

1.求最少给多少学校发软件能遍历所有学校 入度的值即可
2.最少加几条边使得整个图强连通 和之前做的一题很像

还有就是注意cnt为1的情况要特判
技术图片
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=500+5;
const int M=N*N;
int head[M],pos;
struct Edge
{
    int nex,to,v;
}edge[M];
struct node
{
    int s,e;
}s[M];
void add(int a,int b)
{
    edge[++pos].nex=head[a];
    head[a]=pos;
    edge[pos].to=b;
}
int tot,ind,cnt,Stack[N],dfn[N],low[N],vis[N],belong[N],in[N],out[N];
int n,m;
void init()
{
    tot=ind=cnt=pos=0;
    CLR(in,0);
    CLR(out,0);
    CLR(Stack,0);
    CLR(head,0);
    CLR(vis,0);
    CLR(dfn,0);
    CLR(low,0);
}
void tarjan(int x)
{
    dfn[x]=low[x]=++tot;
    Stack[++ind]=x;
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(vis[v])
            low[x]=min(low[x],low[v]);
    }
    if(dfn[x]==low[x])
    {
        cnt++;int v;
        do
        {
            v=Stack[ind--];
            vis[v]=0;
            belong[v]=cnt;
        }
        while(x!=v);
    }
}

int main()
{
   int n;
   RI(n);
   rep(i,1,n)
   {
       int x;
       while(RI(x),x)
       {
           add(i,x);
       }
   }
   rep(i,1,n)
   if(!dfn[i])
    tarjan(i);

   rep(i,1,n)
   {
       int u=belong[i];
       for(int j=head[i];j;j=edge[j].nex)
       {
           int v=belong[edge[j].to];
           if(u!=v)
           in[v]++,out[u]++;
       }
   }
   int q=0,w=0;
   rep(i,1,cnt)
   {
       if(!in[i])q++;
       if(!out[i])w++;
   }

   if(cnt==1)
    cout<<1<<endl<<0<<endl;
   else
   cout<<q<<endl<<max(q,w);
    return 0;
}
View Code

 







P2746 [USACO5.3]校园网Network of Schools 强连通

标签:发送   nbsp   void   input   电脑   分发   lap   back   %s   

原文地址:https://www.cnblogs.com/bxd123/p/10801622.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!