一本通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
原文地址:https://www.cnblogs.com/gaojunonly1/p/10352688.html