您的位置:首页 > 其它

poj 1236 Network of Schools(强连通、缩点、出入度)

2013-10-02 16:17 537 查看
题意:给出一个有向图。1:问至少选出多少个点,才能沿有向边遍历所有节点。2:问至少加多少条有向边,使原图强连通。

分析:第一个问题,缩点后找所有树根(入度为0)。第二个问题,分别找出入度为0和出度为0的所有点,去最大值即为答案。

  关于第二个问题,与这道题很相似。

#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;

const int MAXN=111;

struct Edge{
int v,next;
Edge(){}
Edge(int _v,int _next):v(_v),next(_next){}
}edge[MAXN*MAXN];

int pre[MAXN],low[MAXN],sccno[MAXN],dfs_clock,scc_cnt;
int head[MAXN],tol;

int outmark[MAXN],inmark[MAXN];

stack<int>stk;

void init()
{
tol=0;
memset(head,-1,sizeof(head));
}

void add(int u,int v)
{
edge[tol]=Edge(v,head[u]);
head[u]=tol++;
}

void dfs(int u)
{
int v;
pre[u]=low[u]=++dfs_clock;
stk.push(u);
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;

if(!pre[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}else if(!sccno[v])
low[u]=min(low[u],pre[v]);
}
if(pre[u]==low[u]){
scc_cnt++;
do{
v=stk.top();
stk.pop();
sccno[v]=scc_cnt;
}while(u!=v);
}
}

void find_scc(int n)
{
dfs_clock=scc_cnt=0;
memset(pre,0,sizeof(pre));
memset(low,0,sizeof(low));
memset(sccno,0,sizeof(sccno));

for(int i=1;i<=n;i++)
if(!pre[i])
dfs(i);
}

int main()
{
int n;
scanf("%d",&n);
init();
for(int u=1;u<=n;u++)
{
while(1)
{
int v;
scanf("%d",&v);
if(!v)
break;
add(u,v);
}
}

find_scc(n);

memset(inmark,0,sizeof(inmark));
memset(outmark,0,sizeof(outmark));
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
if(sccno[i]!=sccno[edge[j].v]){
inmark[sccno[edge[j].v]]++;
outmark[sccno[i]]++;
}
}
int inans=0,outans=0;
for(int i=1;i<=scc_cnt;i++)
{
if(!inmark[i])
inans++;
if(!outmark[i])
outans++;
}
printf("%d\n",inans);
if(scc_cnt==1)
printf("0\n");
else
printf("%d\n",max(inans,outans));
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: