• 1553:【例 2】暗的连锁


    1553:【例 2】暗的连锁

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

    【题目描述】

    原题来自:POJ 3417

    Dark 是一张无向图,图中有 N个节点和两类边,一类边被称为主要边,而另一类被称为附加边。

    Dark 有 N–1 条主要边,并且 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% 的数据,1≤N,M≤100;

    对于 100% 的数据,1≤N≤(1*10^{5}),1≤M≤ (2* 10^{5} )。

    数据保证答案不超过 (2 ^ {31}-1)。

    【题解】

    考虑枚举每条主要边删掉后情况,删后原树被分为两块,若中间没有附加边,则ans+m,若有一条则只能删掉这条,若有两条以上则无解。

    判断每条附加边对几条主要边有贡献,发现它只对他两个端点之间的路径有贡献。

    树上差分或者树链剖分均可解决。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int n,m,last[N],size,f[N][20],dep[N],cha[N];
    struct pigu
    {
        int dao,ne;
    }a[N<<1];
    inline void lingjiebiao(int x,int y)
    {
        a[++size].dao=y;
        a[size].ne=last[x];
        last[x]=size;
    }
    inline void dfs1(int now,int fa)
    {
        f[now][0]=fa;dep[now]=dep[fa]+1;
        for(int i=1;f[f[now][i-1]][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
        for(int i=last[now];i;i=a[i].ne)
        {
            if(a[i].dao==fa) continue;
            dfs1(a[i].dao,now);
        }
    }
    inline int get_lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=19;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i];
        if(x==y) return x;
        for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    inline void dfs2(int now)
    {
        for(int i=last[now];i;i=a[i].ne)
        {
            if(f[now][0]==a[i].dao) continue;
            dfs2(a[i].dao);
            cha[now]+=cha[a[i].dao];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x,y;i<=n-1;i++)
        {
            scanf("%d%d",&x,&y);
            lingjiebiao(x,y);
            lingjiebiao(y,x);
        }
        dfs1(1,0);
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            int lca=get_lca(x,y);
            cha[x]++;cha[y]++;cha[lca]-=2;
        }
        dfs2(1);
        int ans=0;
        for(int i=2;i<=n;i++)
        {
            if(cha[i]==0)
                ans+=m;
            if(cha[i]==1) ans++;
        }
        cout<<ans;
    }
    View Code
  • 相关阅读:
    如何让我domain里的机器都跟domain controller的时间保持一致?
    [PowerShell Utils] Create a list of virtual machines based on configuration read from a CSV file in Hyper-V
    Reboot server stuck at “Press ESC in 1 seconds to skip startup.nsh”
    [PowerShell Utils] Remotely install Hyper-V and Failover Cluster feature on a list of windows 2012 servers
    [PowerShell Utils] Automatically Change DNS and then Join Domain
    SharePoint 2016 IT Preview的新feature列表
    LeetCode Permutations问题详解
    Rotate Image 旋转图像
    单链表的快速排序(转)
    anagrams 查找序列里具有相同字符但顺序不同的单词
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12173663.html
Copyright © 2020-2023  润新知