poj 1236

来源:互联网 发布:桌面软件编程语言 编辑:程序博客网 时间:2024/06/05 07:40

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;}
1 0
原创粉丝点击