POJ3177tarjan缩点_构建双连通图

POJ3177tarjan缩点_构建双连通图

根据题意利用tarjan算法进行缩点处理后变成连通无环图,也可以说是一颗树,而且边是双向的所以,如果把这个图变成双连通,那就要对所有度为1的点进行加边处理

所以步骤如下

1·tarjan缩点处理

void tarjan(int u,int pre)
{
    low[u] = dfn[u] = ++idx;
    for(int v = 1;v <= n;v++)
    {
        if(mp[u][v])
        {
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u] = min(low[u],low[v]);
            }
            if(dfn[v] && v != pre)
            {
                low[u] = min(low[u],dfn[v]);
            }
        }
    }
}

2· 计算点的度

for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= n;j++)//计算每个点的度
            {
                if(mp[i][j])
                {
                    if(low[i] != low[j])
                    {
                        cnt[low[j]]++;
                    }
                }
            }
        }

 3·计算加的边数

int ans=0;				//计算度为1的点的个数
		for(int i = 1;i <= n;i++)
        {
			if(cnt[i] == 1) ans++;
		}
		printf("%d\n",(ans + 1) / 2);

 嗯嗯tarjan算法差不多啦

这个题目还出了一个小插曲,就是定义mp时候用的int类型,给爆了,改成bool就好了,其实就该用bool,因为只是一个01存储,但是一想bool和int差的可不是1倍两倍,而是32倍呢(还得看编译器),吓人略略略

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn = 5010;
int n,m;
bool mp[maxn][maxn];
int low[maxn],dfn[maxn];
int idx;
int cnt[maxn];
/*
bool 类型的数据 在内存中只有一位 或0 或1
int 类型的数据 在内存中有16位或32位
*/
void init()
{
    memset(low,0,sizeof(low));
    memset(mp,0,sizeof(mp));
    memset(dfn,0,sizeof(dfn));
    memset(cnt,0,sizeof(cnt));
    idx = 0;
}

void tarjan(int u,int pre)
{
    low[u] = dfn[u] = ++idx;
    for(int v = 1;v <= n;v++)
    {
        if(mp[u][v])
        {
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u] = min(low[u],low[v]);
            }
            if(dfn[v] && v != pre)
            {
                low[u] = min(low[u],dfn[v]);
            }
        }
    }
}
int main()
{
    int u,v;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i = 1;i <= m;i++)
        {
            scanf("%d%d",&u,&v);
            mp[u][v] = mp[v][u] = 1;

        }
        tarjan(1,1);
        for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= n;j++)//计算每个点的度
            {
                if(mp[i][j])
                {
                    if(low[i] != low[j])
                    {
                        cnt[low[j]]++;
                    }
                }
            }
        }
        
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Df_cjc/article/details/81358253
今日推荐