【POJ 3352】 Road Construction

【题目链接】

           点击打开链接

【算法】

         tarjan算法求边双联通分量

【代码】

           

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 1010

int n,m,i,timer,tot;
int u[MAXN],v[MAXN],dfn[MAXN],low[MAXN],degree[MAXN],head[MAXN];

struct Edge
{
    int to,nxt;
} e[MAXN];

inline void add(int u,int v)
{
    tot++;
    e[tot] = (Edge){v,head[u]};
    head[u] = tot;    
}
inline void tarjan(int u,int fa)
{
    int i,v;
    dfn[u] = low[u] = ++timer;
    for (i = head[u]; i; i = e[i].nxt)
    {
        v = e[i].to;
        if (v != fa)
        {
            if (!dfn[v])
            {
                tarjan(v,u);
                low[u] = min(low[u],low[v]);
            } else low[u] = min(low[u],dfn[v]);
        }
    }    
}
inline void calc()
{
    int i,cnt = 0;
    for (i = 1; i <= m; i++)
    {
        if (low[u[i]] != low[v[i]])
        {
            degree[low[u[i]]]++;
            degree[low[v[i]]]++;    
        }    
    }
    for (i = 1; i <= n; i++) cnt += (degree[i] == 1);
    printf("%d\n",(cnt+1)/2);
}
 
int main()
{
    
    scanf("%d%d",&n,&m);
    for (i = 1; i <= m; i++)
    {
        scanf("%d%d",&u[i],&v[i]);
        add(u[i],v[i]);
        add(v[i],u[i]);    
    }
    tarjan(1,-1);
    calc();
    
    return 0;
}

 

posted @ 2018-06-12 18:48  evenbao  阅读(130)  评论(0编辑  收藏  举报