poj 3177 Redundant Paths 边双连通分量+缩点

题意:给定n个点m条边。要使任意两个点可以通过两条严格不同的路径到达。即边不能重复,点可以重复。求需要添加的最小边数


题目就是要求使这个图成为边双连通分量所需添加的最小边数。

我的做法:

将边双连通分量相关的点缩点。然后求出度为1的个数=num。答案就是(num+1)/2或者说是num/2+num%2

理由:度为1的肯定是叶子节点或者根节点。将叶子节点两两配对。如果是奇数的话就任意与一个节点配对成边即可。

我在做边双连通分量缩点的过程异常麻烦。

首先我求出桥,然后删掉这些桥。将连通块缩点(这些连通块是边双连通分量)。然后再计算度数。。写的很多。感觉很麻烦。肯定有更简短的代码。。

---------2014/7/11 在下面还有一个代码 修改过后的。。写法比前面这个简便多了。

//author: CHC
//First Edit Time:	2014-07-11 10:04
//Last Edit Time:	2014-07-11 11:53
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define MAXN 5010
vector <int> e[MAXN];
vector <int> e1[MAXN];
vector <int> e2[MAXN];
int dfn[MAXN],low[MAXN],pre[MAXN],n,m;
int times=0,tot=0;
int du[MAXN];
void tarjan_3(int u){
    dfn[u]=low[u]=++times;
    for(int i=0;i<(int)e[u].size();i++){
        int v=e[u][i];
        if(!dfn[v]){
            pre[v]=u;
            tarjan_3(v);
            low[u]=min(low[u],low[v]);
        }
        else if(pre[u]!=v){
            low[u]=min(low[u],dfn[v]);
        }
    }
}
int vis[MAXN],tots;
void bfs(int u){
    vis[u]=++tots;
    queue <int> q;
    q.push(u);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=0;i<(int)e2[now].size();i++){
            int next=e2[now][i];
            if(vis[next])continue;
            vis[next]=vis[now];
            q.push(next);
        }
    }
}
bool check(int u,int v){
    if(e1[u].empty())return true;
    for(int i=0;i<(int)e1[u].size();i++){
        int v1=e1[u][i];
        if(v1==v)return false;
    }
    return true;
}
char has[MAXN];
void bfs1(int x){
    queue <int> q;
    q.push(x);
    has[x]=1;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=0;i<(int)e1[now].size();i++){
            int next=e1[now][i];
            if(has[next])continue;
            has[next]=1;
            ++du[now];
            ++du[next];
            q.push(next);
        }
    }
}
void solve(){
    tots=times=tot=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan_3(i);
    //qiao
    for(int i=1;i<=n;i++){
        if(pre[i]>0&&dfn[pre[i]]<low[i]){
            //cout<<pre[i]<<"   "<<i<<endl;
            e1[pre[i]].push_back(i);
            e1[i].push_back(pre[i]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<(int)e[i].size();j++){
            int v=e[i][j];
            if(check(i,v)){
                e2[i].push_back(v);
                e2[v].push_back(i);
            }
        }
    }
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            bfs(i);
        }
    }
    memset(du,0,sizeof(du));
    for(int i=0;i<n+10;i++)e1[i].clear();
    for(int i=1;i<=n;i++){
        for(int j=0;j<(int)e[i].size();j++){
            int v=e[i][j];
            if(vis[i]==vis[v])continue;
            e1[vis[i]].push_back(vis[v]);
            e1[vis[v]].push_back(vis[i]);
            //printf("%d-->%d\n",vis[i],vis[v]);
        }
    }
    memset(has,0,sizeof(has));
    for(int i=1;i<=tots;i++)
        if(!has[i])bfs1(i);
    int cnt=0;
    for(int i=1;i<=tots;i++){
        //printf("%d: %d\n",i,du[i]);
        if(du[i]==1)++cnt;
    }
    //printf("tots:%d\n",tots);
    //printf("cnt:%d\n",cnt);
    printf("%d\n",(cnt+1)/2);
    return ;
}

int main()
{
    //freopen("out.txt","r",stdin);
    //freopen("out-2.txt","w",stdout);
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<n+10;i++)e[i].clear();
        for(int i=0;i<n+10;i++)e1[i].clear();
        for(int i=0;i<n+10;i++)e2[i].clear();
        for(int i=0,x,y;i<m;i++){
            scanf("%d%d",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        solve();
    }
    return 0;
}

//author: CHC
//First Edit Time:	2014-07-11 15:40
//Last Edit Time:	2014-07-11 16:26
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define MAXN 5010
struct Edge
{
    int to,next;
    bool vis,bge;
}edge[MAXN*2];
int dfn[MAXN],low[MAXN],pre[MAXN];
int sta[MAXN],bleg[MAXN];
int times,n,m,top;
int tot,head[MAXN];
void Add(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].vis=false;
    edge[tot].bge=false;
    head[u]=tot++;
}
void tarjan_3(int u){
    dfn[u]=low[u]=++times;
    sta[++top]=u;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(edge[i].vis)continue;
        edge[i].vis=edge[i^1].vis=true;
        if(!dfn[v]){
            pre[v]=u;
            tarjan_3(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!bleg[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        bleg[0]++;
        do{
            bleg[sta[top]]=bleg[0];
        }while(sta[top--]!=u);
        bleg[u]=bleg[0];
    }
}
int du[MAXN];
void solve(){
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(pre,0,sizeof(pre));
    memset(bleg,0,sizeof(bleg));
    memset(du,0,sizeof(du));
    top=times=0;
    for(int i=1;i<=n;i++)
        if(!dfn[i]){
            tarjan_3(i);
        }
    for(int i=0;i<tot;i++){
        if(edge[i].bge)continue;
        int u=edge[i].to;
        int v=edge[i^1].to;
        if(pre[v]==u&&dfn[u]<low[v]){
            edge[i].bge=edge[i^1].bge=true;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=head[i];j!=-1;j=edge[j].next){
            int v=edge[j].to;
            if(bleg[i]==bleg[v])continue;
            ++du[bleg[i]];
        }
    }
    int cnt=0;
    for(int i=1;i<=bleg[0];i++){
        if(du[i]==1)++cnt;
    }
    printf("%d\n",(cnt+1)/2);
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        tot=0;
        memset(head,-1,sizeof(head));
        for(int i=0,x,y;i<m;i++){
            scanf("%d%d",&x,&y);
            Add(x,y);
            Add(y,x);
        }
        solve();
    }
    return 0;
}




你可能感兴趣的:(bfs,桥,边双连通分量,缩点,建图)