您的位置:首页 > 其它

poj 1236

2016-04-16 20:15 549 查看
poj 1236

强连通分量 tarjan。第一题,。。

题目:

传送

题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题

1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。

2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

解题思路:

求所有连通分量,然后缩点,构成一个有向无环的图,有多少个入度为0的点就是第一问的答案。

第二问呢,很神奇~

现在图上有n个入度为0的点,编号为0 1 2 .。。N,有m个出度为0的点。

把所有入度为0的点可达的出度0点,添加一条出边。需要n条边。

如果 n>m

那么就是n;否则再加m-n。一共是m

所一第二问是max{m,n}

代码:

zrtorz大神神神。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,t,dfn[110],low[110],num,strong[110];
int ru[110],chu[110];
bool v[110];
int stack[110],p;
int next[10010],ver[10010],head[10010],tot;
struct edge{int st,end;
}a[10010];
void add(int x,int y)
{
tot++;
ver[tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void tarjan(int x)
{
int i;
dfn[x]=low[x]=++num;
stack[++p]=x;v[x]=1;
for(i=head[x];i;i=next[i])
{
if(!dfn[ver[i]])
{
tarjan(ver[i]);
low[x]=min(low[x],low[ver[i]]);
}
else if(v[ver[i]])
low[x]=min(low[x],low[ver[i]]);
}
if(low[x]==dfn[x])
{
int y;
++t;
do
{
y=stack[p--];
v[y]=0;
strong[y]=t;
}
while(y!=x);
}
}
int main()
{
int i,j,k,ans1=0,ans2=0;
cin>>n;
for(i=1;i<=n;i++)
while(scanf("%d",&j)!=EOF&&j!=0)
add(i,j),a[tot].st=i,a[tot].end=j;
for(i=1;i<=n;i++)
{
if(!dfn[i])
tarjan(i);
}
for(i=1;i<=tot;i++)
{
if(strong[a[i].st]==strong[a[i].end])
continue;
chu[strong[a[i].st]]++;
ru[strong[a[i].end]]++;
}
for(i=1;i<=t;i++)
{
if(!ru[i])
ans1++;
}
cout<<ans1<<endl;
if(t==1)
{
cout<<0;
return 0;
}
for(i=1;i<=t;i++)
{
if(!chu[i])
ans2++;
}
ans2=max(ans1,ans2);
cout<<ans2;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj