[poj] 3177 Redundant Paths

原题

这是一道边双联通分量的板子题。
当我们对他缩点后,我们有一棵树,需要添加的边即为缩点后的(leaf+1)/2(把两个叶子连在一起一定是贪心最优解)

#include<cstdio>
#include<algorithm>
#define N 5010
#define M 10010
using namespace std;
int n,m,head[N],cnt=2,t,dfn[N],low[N],sum,from[N],in[N],bel[N],num;
bool is[2*M],vis[N];
struct hhh
{
    int to,next;
}edge[2*M];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
    if (j=='-') j=getchar(),fu=-1;
    for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
    return ans*fu;
}

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

void Tarjan(int x)
{
    dfn[x]=low[x]=++t;
    for (int i=head[x],v;i;i=edge[i].next)
    {
	v=edge[i].to;
	if (i==(from[x]^1)) continue;
	if (!dfn[v])
	{
	    from[v]=i;
	    Tarjan(v);
	    low[x]=min(low[v],low[x]);
	    if (low[v]>dfn[x]) is[i]=is[i^1]=1,num++;
	}
	else low[x]=min(dfn[v],low[x]);
    }
}

void dfs(int x)
{
    vis[x]=1;
    bel[x]=sum;
    for (int i=head[x];i;i=edge[i].next)
    {
	if (is[i] || vis[edge[i].to]) continue;
	dfs(edge[i].to);
    }
}

int main()
{
    n=read();
    m=read();
    for (int i=1,a,b;i<=m;i++)
    {
	a=read();
	b=read();
	add(a,b);
	add(b,a);
    }
    Tarjan(1);
    for (int i=1;i<=n;i++)
	if (!bel[i]) sum++,dfs(i);
    for (int i=2;i<=2*m+2;i++)
	if (is[i]) in[bel[edge[i].to]]++;
    t=0;
    for (int i=1;i<=sum;i++)
	if (in[i]==1) t++;
    printf("%d",(t+1)/2);
    return 0;
}

原文地址:https://www.cnblogs.com/mrha/p/7851902.html