您的位置:首页 > 理论基础 > 计算机网络

2017acm乌鲁木齐赛区网络赛F题tarjan缩点

2017-09-19 21:05 260 查看
poj1236是问把一棵树变成强联通分量,于是答案就是rudu为0的和出度为0的最大值,因为假设入度为0的多一些,先每个出度为0的连接一个入度为0的,那么还剩一些入度为0的,这时候入度为0的随意连接一些出度为0的,都可以通过不停地绕绕绕绕成为一个强联通分量。

这题是把一个有向图变成强联通分量,先把他们缩点,变成很多棵树,然后再求入度为0,和出度为0的总点数那个多,虽然他们是很多棵树的入度点和出度点,但是是一样的,最后总能绕绕绕绕绕变成强联通分量,不需要去管他们是哪棵树上的。

#include<cstdio>
#include<cstring>
#define maxl 10010
#define maxm 100010

int n,m,top,ans,cnt,ff,num;
int rudu[maxl],out[maxl],f[maxl],dfn[maxl],low[maxl],s[maxl],ehead[maxl];
struct ed{int to,nxt;} e[maxm];
bool in[maxl];

void prework()
{
scanf("%d%d",&n,&m);
memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
memset(ehead,0,sizeof(ehead));
memset(rudu,0,sizeof(rudu));memset(out,0,sizeof(out));
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
e[i].to=v;e[i].nxt=ehead[u];ehead[u]=i;
}

}

void tarjan(int u)
{
int v;s[++top]=u;in[u]=true;
dfn[u]=low[u]=++num;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[u])
low[u]=low[v];
}
else
if(in[v] && dfn[v]<low[u])
low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
ff++;
do
{
v=s[top];s[top]=0;top--;
f[v]=ff;
in[v]=false;
}while(v!=u);
}
}

inline int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}

void mainwork()
{
memset(in,false,sizeof(in));
num=0;top=0;ff=0;
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
int v;
for(int u=1;u<=n;u++)
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(f[u]!=f[v])
out[f[u]]++,rudu[f[v]]++;
}
int root=0,leaf=0;
for(int i=1;i<=ff;i++)
{
if(rudu[i]==0) root++;
if(out[i]==0) leaf++;
}
if(ff==1)
ans=0;
else
ans=max(root,leaf);
}

void print()
{
printf("%d\n",ans);
}

int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐