POJ 3352 Road Construction 中一个结论的证明

题面

分析:

很多人都给出了做法,在这里不赘述。大概就是先把桥找出来,然后边双缩点,最后统计新图上的度数。因为缩点后为一棵树,所以度数为1(即为叶子)的点的数目+1再除以2下取整就是答案。

这里主要证明一下为什么是对的。

表达式:\[答案=\lfloor\frac{叶子数+1}{2}\rfloor\]

证明:考虑一棵树中,我们找出带权重心,使得重心下每个子节点的叶子节点数尽量的平均(具体实现不讲了),那么在这棵尽量平均的树上,我们每次取两个根节点下子树不同的叶子节点连边,比如说最左边连最右边,左二连右二……,假如是偶数,那么搞定了。否则,那个点再随便连别的一棵子树的一个叶子(其实不是也行)就OK了。

觉得证明不严谨或者有问题的请指出,共同交流。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
using namespace std; 

const int maxn=1010;
int n,m,tot,head[maxn],cnt,dfn[maxn],low[maxn],c[maxn],ans,d[maxn];
bool br[maxn<<1],vis[maxn];
struct node
{
    int nxt,to;
}edge[maxn<<1];

int read()
{
    int x=0,f=1;
    char c=getchar();
    while (!isdigit(c))
        f=c=='-'?-1:1,c=getchar();
    while (isdigit(c))
        x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}

void add(int u,int v)
{
    edge[++tot]=(node){head[u],v};
    head[u]=tot;
}

void tarjan(int u,int fa)   //get bridges
{
    int i,v;
    low[u]=dfn[u]=++cnt;
    for (i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if (!dfn[v])
        {
            tarjan(v,i);
            low[u]=min(low[u],low[v]);
            if (low[v]>dfn[u])
                br[i]=br[i^1]=1;
        }
        else
        if (i!=(fa^1))
            low[u]=min(low[u],dfn[v]);
    }
}

void dfs(int u,int co)
{
    c[u]=co;
    int i,v;
    for (i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if (br[i]||c[v])
            continue;
        dfs(v,co);
    }
}

int main()
{
    int i,j,u,v;
    n=read();
    m=read();
    tot=1;
    for (i=1;i<=m;i++)
    {
        u=read();
        v=read();
        add(u,v);
        add(v,u);
    }
    for (i=1;i<=n;i++)
        if (!dfn[i])
            tarjan(i,0);
    cnt=0;
    for (i=1;i<=n;i++)
        if (!c[i])
            dfs(i,++cnt);
    for (i=1;i<=n;i++)
        for (j=head[i];j;j=edge[j].nxt)
            if (c[i]!=c[edge[j].to])
            {
                d[c[i]]++;
                d[c[edge[j].to]]++;
            }
    for (i=1;i<=cnt;i++)
        if (d[i]==2)
            ans++;
    printf("%d\n",(ans+1)/2);
    return 0;
}

原文地址:https://www.cnblogs.com/Ronald-MOK1426/p/11776092.html

时间: 2024-11-09 00:36:29

POJ 3352 Road Construction 中一个结论的证明的相关文章

POJ 3352 Road Construction 使得无向图边变双连通图

点击打开链接 Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8168   Accepted: 4106 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of

POJ 3177 Redundant Paths POJ 3352 Road Construction(双连通)

POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的,一份代码能交,给定一个连通无向图,问加几条边能使得图变成一个双连通图 思路:先求双连通,缩点后,计算入度为1的个数,然后(个数 + 1) / 2 就是答案(这题由于是只有一个连通块所以可以这么搞,如果有多个,就不能这样搞了) 代码: #include <cstdio> #include <cstring> #include <algorithm&

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点) ACM 题目地址: POJ 3352 Road Construction POJ 3177 Redundant Paths 题意: 问要添加几条边才能使所给无向图图变成边双连通图. 分析: 边连通度:使无向图G不连通的最少删边数量为其边连通度. 边双连通图:边连通度大于1的无向图. 首先缩点,让图变成一个DAG. 现在问题转化为:在树中至少添加多少条边能使图变

POJ 3352 Road Construction(图论-tarjan)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8647   Accepted: 4318 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

Poj 3352 Road Construction &amp; Poj 3177 Redundant Paths(边双连通分量+缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9465   Accepted: 4699 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&amp;&amp;缩点】

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the r

POJ 3352 Road Construction(无向连通图)

题目地址:POJ 3352 这题就是求最少加多少条边可以使得图为无向双连通图.方法是找度数为1的连通分量,可以只用low来找.然后根据公式(叶子结点数+1)/2即可得到答案.原因是在图中将每两个度数为1的都连起来,度数为2的显然已经可以形成双联通了,因为是无向边,只要加一条,就相当于加了两条有向边,很显然,结果数就是那个公式. 代码如下: #include <iostream> #include <cstdio> #include <string> #include &

二叉树链表中一个结论的证明以及 Successor() 函数中算法的解释

首先, 先明确 “结点 x 的 successor” 的概念. 这句话的概念是, successor 是整个二叉树中, key 仅比 x 的 key 大的结点. 求证: 若 x 有两个孩子, 那么其 successor 没有左孩子. 证明: 若 x 有两个孩子, 则其右子树存在.在二叉树链表中, 对于任意 x 的右子树都是 key 比 x 的 key 大的结点的集合, 即{y|y->key > x->key}.根据 successor  的定义, 若 x->rightChild ≠

POJ 3352 Road Construction(添最少边构造边双连通图的结论)

题意:已知无向图,问添加最少的边使之成为边双连通图 思路:显然先缩点成一棵树,添加最少边使一棵树的边双连通 此处有结论:对于一棵树添加(1+leaf)>>1 条无向边就能构造成一个双连通图,构造方法显然(脑补一下 //216K 63MS C++ 1754B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; c