您的位置:首页 > 其它

codevs爱在心中(强联通分量,缩点,求出度为0的点)缩点模版

2016-06-27 10:48 246 查看
</pre><pre name="code" class="cpp">#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

int head[100009],tot,dfn[100009],low[100009],sta[1000009],top,n,m,pre[300009],edge[300009];
int size[100009],ct[100009],p[100009];
int ans=0,id=0;
bool s[100009];
void add(int x,int y)
{
tot++;edge[tot]=y;pre[tot]=head[x];head[x]=tot;
}
void dfs(int u)
{
dfn[u]=low[u]=++id;
sta[++top]=u;
s[u]=true;

for (int i=head[u];i;i=pre[i])
if (!dfn[edge[i]])
{
dfs(edge[i]);
low[u]=min(low[u],low[edge[i]]);
}else if (s[edge[i]]) low[u]=min(low[u],low[edge[i]]);

if(dfn[u]==low[u])
{
ans++;
while (u!=sta[top+1])
{
s[sta[top]]=false;
ct[sta[top]]=ans;
top--;
size[ans]++;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
ans=0;
tot=0;top=0;
int x,y;
for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y);
for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);
int z=0;
for (int i=1;i<=ans;i++) if (size[i]>1) z++;
printf("%d\n",z);
for (int i=1;i<=n;i++)
for (int j=head[i];j;j=pre[j])
if (ct[i]!=ct[edge[j]])//如果这条边属于两个强联通分量,那么连边
{
p[ct[i]]++;
}//以上两个循环为缩点循环,将每一个强联通分量作为一个点,强联通分量之间连,从新建图
z=0;int t;
for (int i=1;i<=ans;i++) if (p[i]==0&&size[i]>1)
{z++;t=i;}
if (z==0||z>1)
{
printf("-1");
return 0;
}
int ans=0;
for (int i=1;i<=n;i++) if (ct[i]==t) printf("%d ",i);
return 0;
}


。。。。。。
void insert(int u,int v,int h)//插入边,h==0表示缩点前的图,h==1表示缩点后的

{
edge[h][Enum].self=u;
edge[h][Enum].son=v;
edge[h][Enum].next=head[h][u];
head[h][u]=Enum++;

}

。。。。

void Rebuild()//缩点建新图

{

    for(int u=0;u<nu++)
{
for(int i=head[0][u];i!=-1;i=edge[0][i].next)
{
int v=edge[0][i].son;
if(belong[u]!=belong[v])
insert(belong[u],belong[v],1);

}
}

}

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