列表

详情


NC51254. 闇の連鎖

描述

传说中的暗之连锁被人们称为 Dark。Dark 是人类内心的 黑暗的产物,古今中外的勇者们都试图打倒它。经过研究, 你发现 Dark 呈现无向图的结构,图中有 N 个节点和两类边, 一类边被称为主要边,而另一类被称为附加边。Dark 有 N – 1 条主要边,并且 Dark 的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark 还有 M 条附加边。 你的任务是把 Dark 斩为不连通的两部分。一开始 Dark 的附加边都处于无敌状态,你只能选择一条主要边切断。一 旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切 断。但是你的能力只能再切断 Dark 的一条附加边。现在你想要知道,一共有多少种方案可 以击败 Dark。注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断 一条附加边才算击败了 Dark。
 

输入描述

第一行包含两个整数 N 和 M。
之后 N – 1 行,每行包括两个整数 A 和 B,表示 A 和 B 之间有一条主要边。
之后 M 行以同样的格式给出附加边。

输出描述

输出一个整数表示答案。

示例1

输入:

4 1 
1 2 
2 3 
1 4 
3 4

输出:

3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 171ms, 内存消耗: 13788K, 提交时间: 2020-01-26 21:51:22

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 100100;
int fa[N],dp[N],n,m;
vector<int> G[N],q[N];

int v[N];
ll ans;
int get(int x) {
    if(x==fa[x]) return x;
    else return fa[x] = get(fa[x]);
}

void tarjan(int x) {
    v[x] = 1;

    for(auto y:G[x]) {
        if(v[y]) continue;
        tarjan(y);
        fa[y] = x;
    }
    for(auto y:q[x]) {
        if(v[y]==2) {
            int lca = get(y);
            dp[x]++, dp[y]++, dp[lca]-=2;
        }
    }
    v[x] = 2;
}

void dfs(int x,int fa) {
    for(auto y:G[x]) {
        if(y==fa) continue;
        dfs(y,x);
        dp[x] += dp[y];
    }
    if(x!=1 && dp[x]==0) ans += m;
    else if(dp[x]==1) ans++;
}

int main() {
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int a,b,i=1;i<n;i++) {
        cin>>a>>b;
        fa[i] = i;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    fa[n] = n;
    for(int a,b,i=0;i<m;i++) {
        cin>>a>>b;
        q[a].push_back(b);
        q[b].push_back(a);
    } 
    tarjan(1);
    dfs(1,0);
    cout<<ans<<endl;
    return 0;
}


C++ 解法, 执行用时: 224ms, 内存消耗: 10000K, 提交时间: 2022-02-11 11:21:12

#include<bits/stdc++.h>
using namespace std;
int n,m,h[100001],e[200001],ne[200001],tot,p[100001],mk[100001],d[100001],ans,a,b;
vector<int> qr[100001];
void add(int a,int b){e[++tot]=b;ne[tot]=h[a];h[a]=tot;}
int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
void tj(int x){
    mk[x]=1;
    for(int i=h[x];i;i=ne[i]){int y=e[i];if(mk[y])continue;tj(y);p[y]=x;}
    mk[x]=2;
    for(int y:qr[x])if(mk[y]==2)d[x]++,d[y]++,d[find(y)]-=2;
}
int dfs(int x,int fa){
    int res=d[x];
    for(int i=h[x];i;i=ne[i]){
        int y=e[i];
        if(y==fa)continue;
        int s=dfs(y,x);
        if(!s)ans+=m;
        else if(s==1)ans++;
        res+=s;
    }
    return res;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n-1;i++)cin>>a>>b,add(a,b),add(b,a);
	for(int i=1;i<=n;i++)p[i]=i;
    for(int i=0;i<m;i++)cin>>a>>b,qr[a].push_back(b),qr[b].push_back(a);
    tj(1);
    dfs(1,-1);
    cout<<ans;
	return 0; 
}

上一题