• 一本通1553【例 2】暗的连锁


    1553:【例 2】暗的连锁

    时间限制: 1000 ms         内存限制: 524288 KB

    题目描述

    原题来自:POJ 3417

    Dark 是一张无向图,图中有 N 个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark 有 N1 条主要边,并且 Dark 的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark 还有 M 条附加边。

    你的任务是把 Dark 斩为不连通的两部分。一开始 Dark 的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断 Dark 的一条附加边。

    现在你想要知道,一共有多少种方案可以击败 Dark。注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断一条附加边才算击败了 Dark。

    输入格式

    第一行包含两个整数 N 和 M;

    之后 N – 1 行,每行包括两个整数 A 和 B,表示 A 和 B 之间有一条主要边;

    之后 M 行以同样的格式给出附加边。

    输出格式

    输出一个整数表示答案。

    样例

    样例输入

    4 1 
    1 2 
    2 3 
    1 4 
    3 4

    样例输出

    3

    数据范围与提示

    对于 20% 的数据,1N,M100;

    对于 100% 的数据,1N10^5,1M2×10^5。数据保证答案不超过 2^31

     sol:在一棵树上去掉一条边后一定会不连通,但是还有m条附加边,就用差分记录一条路径(或边)上覆盖了几条附加边,0:ans+=m ; 1:ans++; >1: cnotinue

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100005,M=200005;
    int n,m;
    struct Tree
    {
        int tot,Next[M],to[M],head[N];
        inline void add(int x,int y)
        {
            Next[++tot]=head[x];
            to[tot]=y;
            head[x]=tot;
            return;
        }
        int F[N][23],Depth[N];
        inline void dfs(int x,int fa)
        {
            int i;
            F[x][0]=fa; Depth[x]=Depth[fa]+1;
            for(i=head[x];i;i=Next[i]) if(to[i]!=fa)
            {
                dfs(to[i],x);
            }
            return;
        }
        inline void Pre()
        {
            int i,j;
            dfs(1,1);
    //        for(i=1;i<=n;i++)
    //        {
    //            printf("fa[%d]=%d
    ",i,F[i][0]);
    //        }
    //        exit(0);
            for(i=1;i<=19;i++)
            {
                for(j=1;j<=n;j++) F[j][i]=F[F[j][i-1]][i-1];
            }
            return;
        }
        inline int Ask_Lca(int x,int y)
        {
            int i;
            if(Depth[x]<Depth[y]) swap(x,y);
            for(i=19;~i;i--) if(Depth[F[x][i]]>=Depth[y])
            {
                x=F[x][i];
            }
            if(x==y) return x;
            for(i=19;~i;i--) if(F[x][i]!=F[y][i])
            {
                x=F[x][i]; y=F[y][i];
            }
            return F[x][0];
        }
        int Chafen[N];
        inline void Ins(int x,int y)
        {
            Chafen[x]++; Chafen[y]++; Chafen[Ask_Lca(x,y)]-=2;
            return;
        }
        inline void Dfs(int x)
        {
    //        printf("x=%d
    ",x);
            int i;
            for(i=head[x];i;i=Next[i]) if(to[i]!=F[x][0])
            {
                Dfs(to[i]); Chafen[x]+=Chafen[to[i]];
            }
            return;
        }
    }T;
    int main()
    {
    //    freopen("yam0.in","r",stdin);
        int i,x,y;
        scanf("%d%d",&n,&m);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            T.add(x,y); T.add(y,x);
        }
        T.Pre();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            T.Ins(x,y);
        }
        T.Dfs(1);
        int ans=0;
        for(i=2;i<=n;i++)
        {
            switch (T.Chafen[i])
            {
                case 0:
                    ans+=m;
                    break;
                case 1:
                    ans++;
                    break;
                default:
                    break;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    /*
    input
    4 1
    1 2 
    2 3 
    1 4 
    3 4
    output
    3
    */
    View Code
  • 相关阅读:
    判断以下字符串中出现次数最多的字符,并且算出该字符出现的次数
    status的状态码
    call和apply的区别?
    闭包
    $(document).ready和window. onload的区别
    python_pandas常用操作
    python经典例题
    爬B站并保存成csv文件。提供数据
    data_analysis:初识numpy
    01爬取豆瓣网电影数据进行numpy的练习
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10352688.html
Copyright © 2020-2023  润新知