【双连通分量】POJ 3352 3177

POJ 3352 跟POJ 3177其实是一样的,只不过3177可能有重边,要特判。

3352问改造后去掉一条边仍然连通,3177问改造后任意两点至少有两条不同的路,其实是一样的,都是先找出桥,把各分量缩成一点变成一棵树,结果就是(子叶数+1)/2

#define N 1005
vector<int> v[N];
int low[N];
bool vis[N];
int du[N];
int cnt;
void dfs(int u,int fa){
    vis[u] = 1;
    int i;
    low[u] = ++cnt;
    for(i=0;i<v[u].size();i++){
        int vv = v[u][i];
        if(vv == fa)continue;
        if(!vis[vv]){
            dfs(vv,u);
        }
        if(low[vv]<low[u])low[u] = low[vv];
    }
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) != -1){
        int i,j;
        for(i=0;i<=n;i++){
            v[i].clear();
            vis[i] = 0;
            du[i] = 0 ;
        }
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            v[a].push_back(b);
            v[b].push_back(a);
        }
        cnt=0;
        dfs(1,1);
        for(i=1;i<=n;i++){
            for(j=0;j<v[i].size();j++){
                int u = v[i][j];
                if(low[i]!=low[u])du[low[i]]++;
            }
        }
        int ans=0;
        for(i=1;i<=n;i++){
            if(du[i] == 1)ans++;
        }
        printf("%d\n",(ans+1)/2);
    }
    return 0;
}

POJ 3177

这里我不明白

2 2

1 2

1 2

为啥这组数据的答案是1,你看看,1,2已经处在同一个双连通分量里已经没有必要再添加额外的边了,poj的数据真怪异

#define N 5005
vector<int> v[N];
int low[N];
bool vis[N];
int du[N];
int cnt;
bool g[N][N];
void dfs(int u,int fa){
    vis[u] = 1;
    int i;
    low[u] = ++cnt;
    for(i=0;i<v[u].size();i++){
        int vv = v[u][i];
        if(vv == fa)continue;
        if(!vis[vv]){
            dfs(vv,u);
        }
        if(low[vv]<low[u])low[u] = low[vv];
    }
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) != -1){
        int i,j;
        memset(g,0,sizeof(g));
        for(i=0;i<=n;i++){
            v[i].clear();
            vis[i] = 0;
            du[i] = 0 ;
        }
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            if(!g[a][b]){
            v[a].push_back(b);
            v[b].push_back(a);
            g[a][b] = g[b][a] = 1;
            }
        }
        cnt=0;
        dfs(1,1);
        for(i=1;i<=n;i++){
            for(j=0;j<v[i].size();j++){
                int u = v[i][j];
                if(low[i]!=low[u])du[low[i]]++;
            }
        }
        int ans=0;
        for(i=1;i<=n;i++){
            if(du[i] == 1)ans++;
        }
        printf("%d\n",(ans+1)/2);
    }
    return 0;
}




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值