• 洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths 解题报告


    P2860 [USACO06JAN]冗余路径Redundant Paths

    题目描述

    为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择.

    每对草场之间已经有至少一条路径.给出所有R(F-1≤R≤10000)条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量, 路径由若干道路首尾相连而成.两条路径相互分离,是指两条路径没有一条重合的道路.但是,两条分离的路径上可以有一些相同的草场. 对于同一对草场之间,可能已经有两条不同的道路,你也可以在它们之间再建一条道路,作为另一条不同的道路.

    输入输出格式

    输入格式:

    Line 1: Two space-separated integers: F and R

    Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.

    输出格式:

    Line 1: A single integer that is the number of new paths that must be built.


    其实题目并不难,但我想太复杂了,各种仙人掌仙人掌的。。

    我们考虑如果一对点合法,一定是它们的路径上有环,如果所有的点对都合法,那么每个点至少在一个环上。

    然而这样并不充分。

    考虑它在什么时候是充分的。

    我们可以先把原有的环缩掉,因为原有的环中的所有点都等价

    好了,现在有一颗树,我们再探讨一下充分吗,经过充分的模拟,我们发现这是充分的

    如何令树上所有的点都在环上呢?

    我们两两连接叶子节点

    此题需要判重边


    Code:

    #include <cstdio>
    #include <cstring>
    #include <map>
    using namespace std;
    int min(int x,int y){return x<y?x:y;}
    const int N=5010;
    int head[N],Next[N<<2],to[N<<2],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
    }
    int dfn[N],low[N],s[N],in[N],is[N],ha[N],tot,dfs_clock;
    int ans,cnt0,n,m,n0;
    void tarjan(int now,int fa)
    {
        dfn[now]=low[now]=++dfs_clock;
        s[++tot]=now;in[now]=1;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(v==fa) continue;
            if(!dfn[v])
            {
                tarjan(v,now);
                low[now]=min(low[now],low[v]);
            }
            else if(in[v])
                low[now]=min(low[now],dfn[v]);
        }
        if(low[now]==dfn[now])
        {
            int k;n0++;
            do
            {
                k=s[tot--];
                ha[k]=n0;
                in[k]=0;
            }while(k!=now);
        }
    }
    map <int,map <int,int> > used;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int u,v,i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            if(used[u][v]) continue;
            used[u][v]=used[v][u]=1;
            add(u,v),add(v,u);
        }
        tarjan(1,0);
        memset(in,0,sizeof(in));
        for(int u=1;u<=n;u++)
            for(int i=head[u];i;i=Next[i])
                if(ha[u]!=ha[to[i]])
                    in[ha[u]]++;
        for(int i=1;i<=n0;i++)
            if(in[i]==1) ans++;
        printf("%d
    ",ans+1>>1);
        return 0;
    }
    
    

    2018.8.8

  • 相关阅读:
    【t035】收入计划
    【Z10】引水入城
    【a702】贷款利率
    【t057】任务分配
    10个带源码的充满活力的Web设计教程
    PHP和MySQL Web开发(原书第4版) 高清PDF+源代码
    Optimizing concurrent accesses in a directory-based coherency protocol
    献给母亲节的沙画,致此生最爱——母亲!
    献给母亲节的沙画,致此生最爱——母亲!
    C#一些实用的工具
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9442206.html
Copyright © 2020-2023  润新知