校园网络
时间限制: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
来源
POJ改编
对于这道题,我们可以将校园网络看作一个DAG图,然后通过tarjan算法判断此DAG图是否强连通,如果不是强连通图,至少添加多少条有向边成为强连通图。
解题步骤:
- tarjan算法计算强连通分量的个数
- 缩点
- 统计缩点后的强连通分量的入度和出度
- 选择入度为0和出度为0的较大者即是结果(因为强连通图没有入度或者出度为0的点,我们要消灭0度~)
#include <stdio.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <string.h>
using namespace std;
vector<int>link[105];
stack<int>s;
bool inStack[105];
int dfn[105],low[105],point[105],in[105],out[105];
int m,time,cnt,top;
void tarjan(int root)
{
dfn[root]=low[root]=++time;
s.push(root);
inStack[root]=true;
for(int i=0;i<link[root].size();i++)
{
int edge=link[root][i];
if(!low[edge])
{
tarjan(edge);
low[root]=min(low[edge],low[root]);
}
else if(inStack[edge])
{
low[root]=min(low[edge],low[root]);
}
}
if(low[root]==dfn[root])
{
cnt++;
do
{
top=s.top();s.pop();
inStack[top]=false;
point[top]=cnt;
}while(top!=root);
}
}
void dotarjan()
{
for(int i=1;i<=m;i++)
{
if(!low[i])
tarjan(i);
}
if(cnt==1)
{
printf("0\n");
return ;
}
for(int i=1;i<=m;i++)
{
for(int j=0;j<link[i].size();j++)
{
if(point[i]==point[link[i][j]]) continue;
out[point[i]]++;
in[point[link[i][j]]]++;
}
}
int innum=0,outnum=0;
for(int i=1;i<=cnt;i++)
{
if(!in[i]) innum++;
if(!out[i]) outnum++;
}
printf("%d\n",max(innum,outnum));
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cnt=time=0;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(link,0,sizeof(link));
memset(point,0,sizeof(point));
memset(inStack,false,sizeof(inStack));
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x;
while(~scanf("%d",&x)&&x)
{
link[i].push_back(x);
}
}
dotarjan();
}
}