您的位置:首页 > 其它

POJ 1236 Network of Schools 强连通图 tarjan

2011-10-30 15:59 387 查看
题意:

每个学校有他的对象名单。即给你一个有向图。

问题一:要求信息从某些节点进去,能到达所有其它节点。求出“某些节点”这个节点集合的最小值。

问题二:要求添加“某些有向边”,满足无论信息从哪个节点进入,都能传达到所有节点。求“某些有向边“这个集合的最小值。

思路:

先用tarjan求出强连通分量,然后缩点形成一个有向无环图。

有向无环图肯定存在入度为0的节点。

入度为0的节点的个数=问题1的答案。

对于问题二。其实不难。注意到缩点后形成的是有个有向五环图。

可以看成森林,即多棵树。查找根节点和叶子节点,即入度为0的节点和出度为0的节点。

要让一棵树为连通,很直观的就可以看出,最简单的办法就是将叶子节点直接连在根节点上。

但是注意处理当给的图是一个连通图这个特例。

#include<iostream>
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
const int N=105;
int n;
int mat

;
int dfn
;
int low
;
int index=1;
bool instack
;
int stack
;
int belong
;
int indgr
;
int outdgr
;
int sp=0;
int sccn;
void tarjan(int i)
{
dfn[i]=low[i]=index++;
stack[sp++]=i;
instack[i]=true;
for(int j=1;mat[i][j]!=0;j++)
{
int v=mat[i][j];
if(!dfn[v])
{
tarjan(v);
low[i]=min(low[v],low[i]);
}
else if(instack[v])
{
low[i]=min(dfn[v],low[i]);
}
}
if(low[i]==dfn[i])
{
sccn++;
int j;
do
{
j=stack[--sp];
instack[j]=false;
belong[j]=i;
}while(j!=i);
}
}
void solve()
{
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;mat[i][j];j++)
{
int v=mat[i][j];
if(belong[v]!=belong[i])
{
indgr[belong[v]]++;
outdgr[belong[i]]++;
}
}
}
int insum=0;
int outsum=0;
for(int i=1;i<=n;i++)
{
if(belong[i]==i)
{
if(indgr[i]==0)//每棵树的根节点和
{
insum++;
}
if(outdgr[i]==0)//每个树的叶子节点和
{
outsum++;
}
}
}
printf("%d\n",insum);
if(sccn==1)
printf("0\n");
else
printf("%d\n",max(outsum,insum));
}
int main()
{

scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int to;
int j=1;
do
{
scanf("%d",&to);
mat[i][j++]=to;
}while(to!=0);
}
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: