poj 3352 Road Construction

http://poj.org/problem?id=3352

题意:给一个无向图,加上最少的边,使得改造后的图中去掉任意一条边后图依然连通。

思路:容易想到有环,则环上的点之间不会有问题,所以先首进行缩点,然后形成一棵树,记叶子数为N。再不断进行加边成环缩点可知最终结果为(N+1)/2。N=1时要特判。

View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
using namespace std;

const int maxn = 1005;
struct nd
{
        int u,v,next;
}edge[maxn*2];
int head[maxn],vis[maxn],dfn[maxn],low[maxn],belong[maxn],st[maxn],in[maxn];
int ecnt,cnt,idx,tp;

void add(int u,int v)
{
        edge[ecnt].u = u;
        edge[ecnt].v = v;
        edge[ecnt].next = head[u];
        head[u] = ecnt++;
}

void tarjan(int pre,int u)
{
        int i,v,flag = 1;
        dfn[u] = low[u] = ++idx;
        vis[u] = 1;
        st[++tp] = u;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(v==pre&&flag){flag = 0; continue;}
                if(!dfn[v]){
                        tarjan(u,v);
                        low[u] = min(low[v],low[u]);
                }else if(vis[u]) low[u] = min(dfn[v],low[u]);
        }
        if(dfn[u]==low[u])
        {
                cnt++;
                do{
                        v = st[tp--];
                        vis[v] = 0;
                        belong[v] = cnt;
                }while(v!=u);
        }
}

void processing()
{
        int i,j,k,t,n,m,u,v;
        while(scanf("%d%d",&n,&m)==2)
        {
                MSET(vis,0);
                MSET(dfn,0);
                MSET(in,0);
                MSET(head,-1);
                ecnt = cnt = idx = tp = 0;
                for(i = 0; i < m; ++ i)
                {
                        scanf("%d %d",&u,&v);
                        add(u,v); add(v,u);
                }
                for(i = 1; i <= n; ++ i)if(!dfn[i]) tarjan(-1,i);
                for(i = 0; i < ecnt; ++ i)
                {
                        u = belong[edge[i].u];
                        v = belong[edge[i].v];
                        if(u!=v){in[v]++; in[u]++;}
                }
                k = 0;
                for(i = 1; i <= cnt; ++ i) if(in[i]==2)k++;
                if(k==1){puts("0"); continue;}
                printf("%d\n",(k+1)/2);
        }
}

int main()
{
        processing();
        return 0;
}

 

 

posted on 2012-07-04 22:22  aigoruan  阅读(109)  评论(0)    收藏  举报

导航