zoukankan      html  css  js  c++  java
  • nyoj 120 校园网络(求添加多少条边使整个图强连通)

    校园网络

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:5
     
    描述

    南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件。但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件。

    现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件可用。

     
    输入
    第一行输入一个整数T,表示测试数据的组数(T<10)
    每组测试数据的第一行是一个整数M,表示共有M个系(2<=M<=100)。
    随后的M行,每行都有一些整数,其中的第i行表示系i允许这几个系复制并使用系i的软件。每行结尾都是一个0,表示本行输入结束。如果某个系不允许其它任何系使用该系软件,则本行只有一个0.
    输出
    对于每组测试数据,输出最少需要添加的这种允许关系的个数。
    样例输入
    1
    5
    2 4 3 0
    4 5 0
    0
    0
    1 0
    样例输出
    2

    题解:求出所有的scc并缩点后,记录每个scc的入度和出度,取入度为0的数和出度等于0的数的 的最大值即为要添加的边
    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cstdio> 
    #include<string>
    #include<math.h>
    #include<algorithm>
    #define LL long long
    #define PI atan(1.0)*4
    #define DD double
    #define MAX 20000
    #define mod 100
    #define dian 1.000000011
    #define INF 0x3f3f3f
    using namespace std;
    int head[MAX],ans;
    int low[MAX],dfn[MAX];
    int instack[MAX];
    int n,m;
    int in[MAX],out[MAX];
    int scccnt,dclock,sccno[MAX];
    stack<int>s;
    vector<int>newmap[MAX];
    struct node
    {
    	int u,v,next;
    }edge[MAX];
    void add(int u,int v)
    {
    	edge[ans].u=u;
    	edge[ans].v=v;
    	edge[ans].next=head[u];
    	head[u]=ans++;
    }
    void init()
    {
    	ans=0;
    	memset(head,-1,sizeof(head));
    }
    void tarjan(int u)
    {
    	int v,i,j;
    	s.push(u);
    	instack[u]=1;
    	low[u]=dfn[u]=++dclock;
    	for(i=head[u];i!=-1;i=edge[i].next)
    	{
    		v=edge[i].v;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(instack[v])
    		low[u]=min(low[u],dfn[v]);
    	}
    	if(low[u]==dfn[u])
    	{
    		scccnt++;
    		while(1)
    		{
    			v=s.top();
    			s.pop();
    			instack[v]=0;
    			sccno[v]=scccnt;
    			if(v==u)
    			    break;
    		}
    	}
    }
    void find(int l,int r)
    {
    	memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        memset(sccno,0,sizeof(sccno));
        dclock=scccnt=0;
        for(int i=l;i<=r;i++)
        {
        	if(!dfn[i])
        	    tarjan(i);
        }
    }
    void suodian()
    {
    	int i;
    	for(i=1;i<=scccnt;i++)
    	{
    		newmap[i].clear();
    		in[i]=0;out[i]=0;
    	}
    	for(i=0;i<ans;i++)
    	{
    		int u=sccno[edge[i].u];
    		int v=sccno[edge[i].v];
    		if(u!=v)
    		{
    			newmap[u].push_back(v);
    			in[v]++;
    			out[u]++;
    		}
    	}
    }
    void solve()
    {
        int i,j;
        if(scccnt==1)
        {
            printf("0
    ");
            return ;
        }
        else
        {
            int minn=0;
            int maxx=0;
            for(i=1;i<=scccnt;i++)
            {
                if(!in[i])
                    minn++;
                if(!out[i])
                    maxx++;
            }
            printf("%d
    ",max(minn,maxx));
        }
    }
    int main()
    {
    	int j,i,sum,l,t,k;
        scanf("%d",&t);
        while(t--)
        {
        	scanf("%d",&m);
        	init();
        	for(i=1;i<=m;i++)
        	{
        		while(scanf("%d",&n),n)
        			add(i,n);
        	}
        	find(1,m);
        	suodian();
        	solve();
        }
    	return 0;
    }
    
     
    

      

  • 相关阅读:
    轻轻松松看懂Spring AOP源码
    centos7安装openjdk8
    使用fiddler做弱网测试
    测试术语-好东西要跟大家一块分享-2
    测试思想-好东西与大家分享-1
    session、token、cookie的区别
    接口测试和功能测试的区别
    常见bug解析-移动端
    接口测试的简介
    软件测试基本理论
  • 原文地址:https://www.cnblogs.com/tonghao/p/5342244.html
Copyright © 2011-2022 走看看