USACO Section 5.3 Network of Schools

来源:互联网 发布:知道软件 编辑:程序博客网 时间:2024/06/05 00:05

题意:

一幅有向图  第一问选择最少的点当起点  使得从某一起点出发可以到图中任何一点  第二问最少加多少边可以使任意两点可达


思路:

久违的强连通缩点题

首先tarjan

然后对强连通分量缩成的点统计入度和出度

最后

对于第一问起点数量即入度为0点数量(因为它们不可以被别人到达)

第一问特殊情况  图中任意两点可达  那么你最少也要选一个起点(要不没地方开始走啊…)

对于第二问答案即max(入度为0点,出度为0点) 简单的解释一下就是最少连边的方案就是一个出度为0点连向一个入度为0点以此构成环  如果某一种点多出来几个  就再多连几条边

第二问特殊情况  图中任意两点可达  这时明显答案为0  但是通过求max的结果是1要修正一下


代码:

/*ID: housera1PROG: schlnetLANG: C++*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 110int n,cnt,idx,top;int maz[N][N],low[N],dfn[N],st[N],inst[N],belong[N],in[N],out[N];void tarjan(int u){    int i,v;    dfn[u]=low[u]=++idx;    st[top++]=u;    inst[u]=1;    for(i=1;i<=n;i++)    {        if(maz[u][i])        {            if(!dfn[i])            {                tarjan(i);                low[u]=min(low[u],low[i]);            }            else if(inst[i]) low[u]=min(low[u],dfn[i]);        }    }    if(dfn[u]==low[u])    {        cnt++;        do        {            v=st[--top];            belong[v]=cnt;            inst[v]=0;        }while(v!=u);    }}int main(){    int Debug=0;    if(!Debug)    {        freopen("schlnet.in","r",stdin);        freopen("schlnet.out","w",stdout);    }    int i,j,u,v,ans;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        while(~scanf("%d",&j))        {            if(!j) break;            maz[i][j]=1;        }    }    for(i=1;i<=n;i++)    {        if(!dfn[i]) tarjan(i);    }    //printf("%d\n",cnt);    //for(i=1;i<=n;i++) printf("%d %d\n",i,belong[i]);    for(i=1;i<=n;i++)    {        u=belong[i];        for(j=1;j<=n;j++)        {            v=belong[j];            if(maz[i][j]&&u!=v)            {                out[u]++;                in[v]++;            }        }    }    //for(i=1;i<=cnt;i++) printf("%d in %d out %d\n",i,in[i],out[i]);    for(i=1,ans=0;i<=cnt;i++)    {        if(!in[i]) ans++;    }    ans=max(ans,1);    printf("%d\n",ans);    for(i=1,u=0,v=0;i<=cnt;i++)    {        if(!in[i]) u++;        if(!out[i]) v++;    }    ans=max(u,v);    if(cnt==1) ans=0;    printf("%d\n",ans);    return 0;}


0 0
原创粉丝点击