POJ1236 Network of Schools 强连通+缩点

来源:互联网 发布:手机淘宝访问受限 编辑:程序博客网 时间:2024/05/16 10:59

题目链接:

poj1236




题意:

给出一幅有向图,给出图中所有的边。问:

1.要遍历完图的所有顶点,需要遍历多少次(可以从不同起点)

2.要想只遍历一次,经过图中所有顶点(强连通)最少 需要增加多少条边



题解思路:

首先就是缩点重新建图

对于问题1:

要遍历整个图,只需要从图的所有起点开始遍历

这里图中的起点就是入度为0的点,起点个数即为遍历次数。

对于问题2:

要想使原图成为强连通图

需要保证图中没有入度为0或出度为0的顶点;

而每增加一条边 的  最优连接策略 是   从一个出度为0的顶点到一个入度为0的顶点

这样 需要增加的最少边数即为   入度为0的顶点个数 和   出度为0的顶点个数   之间的最大值


另外需要注意图中只有一个强连通分量的特殊情况(重建图后只有一个顶点):

需要的遍历次数为1

需要的最少边数为0


代码:

#include<iostream>#include<cstdio>#include<cstring>#define maxn 105using namespace std;struct node{    int to,next;}edge[maxn*maxn];int head[maxn];int s;int dfn[maxn],low[maxn],num;int insta[maxn],sta[maxn],top;int belong[maxn],block;void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(insta,0,sizeof(insta));    memset(belong,0,sizeof(belong));    top=num=s=block=0;}void Tarjan(int u,int pre){    dfn[u]=low[u]=++num;    insta[u]=1;    sta[top++]=u;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(!dfn[v])        {            Tarjan(v,u);            low[u]=min(low[u],low[v]);        }        else if(insta[v])            low[u]=min(low[u],dfn[v]);    }    if(low[u]==dfn[u])    {        int d=-1;        block++;        while(d!=u)        {            d=sta[--top];            insta[d]=0;            belong[d]=block;        }    }}void rebuild(int n){    int in[maxn]={0};    int out[maxn]={0};    int u,v;    for(int i=1;i<=n;i++)    {        u=belong[i];        for(int j=head[i];j!=-1;j=edge[j].next)        {            v=edge[j].to;            v=belong[v];            if(u!=v)            {                in[v]++;                out[u]++;            }        }    }    int s1=0,s2=0;    for(int i=1;i<=block;i++)    {        if(!in[i])            s1++;        if(!out[i])            s2++;    }    if(s1==0)        cout<<1<<endl;    else        cout<<s1<<endl;    if(block==1)        cout<<0<<endl;    else        cout<<max(s1,s2)<<endl;}int main(){//    freopen("in.txt","r",stdin);    int n,a,b;    while(~scanf("%d",&n))    {        init();        for(int i=1;i<=n;i++)        {            while(scanf("%d",&a)&&a)            {                edge[s]={a,head[i]};                head[i]=s++;            }        }        for(int i=1;i<=n;i++)            if(!dfn[i])                Tarjan(i,-1);        rebuild(n);    }    return 0;}




0 0
原创粉丝点击