您的位置:首页 > 其它

POJ 1236 Network of Schools [强连通分量]

2017-08-24 20:36 375 查看
题意:给出一张有向图,求要添加最少多少条边,可以让每一个点后能到达其他点。

题解:典型的强连通分量缩点建图。找到入度为0和出度为0的点,他们的最大值就是答案。注意:当点只有1个的时候要特判输出0。

AC代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#define N 105
using namespace std;
int n;
struct edge
{
int v,next;
edge(){}
edge(int v,int next)
{
this->v=v;
this->next=next;
}
}ed[N*N];
int head
,lnum;
void addline(int u,int v)
{
ed[lnum]=edge(v,head[u]);
head[u]=lnum++;
}
int ru
,ch
;
int index=0;
int dfn
,low
,sta
,scc
;
int top=0,sccnum=0;
void tarjan(int root)
{
dfn[root]=low[root]=++index;
sta[top++]=root;
for(int i=head[root];~i;i=ed[i].next)
{
int y=ed[i].v;
if(!dfn[y])
{
tarjan(y);
low[root]=min(low[root],low[y]);
}
else if(!scc[y])
{
low[root]=min(low[root],dfn[y]);
}
}
if(low[root]==dfn[root])
{
int x;
sccnum++;
do
{
x=sta[--top];
scc[x]=sccnum;
}while(x!=root);
}
}
int main()
{
scanf("%d",&n);
memset(head,-1,sizeof(head));
lnum=0;
for(int i=1;i<=n;i++)
{
int k=1;
while(1)
{
scanf("%d",&k);
if(k==0)break;
addline(i,k);
}
}
int sum=0;
for(int i=1;i<=n;i++)
if(dfn[i]==0)
tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=ed[j].next)
{
int t1=scc[i],t2=scc[ed[j].v];
if(t1!=t2)
{
ru[t2]++;
ch[t1]++;
}
}
}
int sum1=0;
for(int i=1;i<=sccnum;i++)
{
if(ru[i]==0)
sum++;
if(ch[i]==0)
sum1++;
}
int sum2;
if(sccnum==1)sum2=0;
else sum2=max(sum,sum1);
printf("%d\n%d\n",sum,sum2);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: