[BZOJ 1718] Redundant Paths

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=1718

[算法]

        用Tarjan算法找出所有e-DCC(边-双联通分量),然后将这张图缩点,答案即为(缩点后的树的叶子节点的个数 + 1) / 2

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 5010
#define MAXM 10010

struct edge
{
        int to,nxt;
} e[MAXM << 1];

int i,n,m,cnt,s,timer,tot;
int head[MAXN],u[MAXM],v[MAXM],low[MAXN],dfn[MAXN],belong[MAXN],degree[MAXN];
bool is_bridge[MAXM << 1];

inline void addedge(int u,int v)
{
        tot++;
        e[tot] = (edge){v,head[u]};
        head[u] = tot;
}
inline void tarjan(int u,int t)
{
        int i,v;
        dfn[u] = low[u] = ++timer;
        for (i = head[u]; i; i = e[i].nxt)
        {
                v = e[i].to;
                if (!dfn[v])
                {
                        tarjan(v,i);
                        low[u] = min(low[u],low[v]);
                        if (low[v] > dfn[u])
                                is_bridge[i] = is_bridge[i ^ 1] = true;    
                }    else if (i != (t ^ 1)) low[u] = min(low[u],dfn[v]);
        }        
}
inline void dfs(int u)
{
        int i,v;
        belong[u] = cnt;
        for (i = head[u]; i; i = e[i].nxt)
        {
                v = e[i].to;
                if (!belong[v] && !is_bridge[i])
                        dfs(v);        
        }        
}
 
int main() 
{
        
        scanf("%d%d",&n,&m);
        tot = 1;
        for (i = 1; i <= m; i++)
        {
                scanf("%d%d",&u[i],&v[i]);
                addedge(u[i],v[i]);
                addedge(v[i],u[i]);        
        }
        for (i = 1; i <= n; i++)
        {
                if (!dfn[i])
                        tarjan(i,0);        
        }
        for (i = 1; i <= n; i++)
        {
                if (!belong[i])
                {
                        cnt++;
                        dfs(i);        
                }        
        }
        for (i = 1; i <= m; i++)
        {
                if (belong[u[i]] != belong[v[i]])
                {
                        degree[belong[u[i]]]++;
                        degree[belong[v[i]]]++;
                }
        }
        for (i = 1; i <= cnt; i++) s += (degree[i] == 1);
        printf("%d\n",(s + 1) / 2);
        
        return 0;
    
}

 

posted @ 2018-08-07 11:50  evenbao  阅读(167)  评论(0编辑  收藏  举报