列表

详情


NC50467. 暗的连锁

描述

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++(g++ 7.5.0) 解法, 执行用时: 156ms, 内存消耗: 15412K, 提交时间: 2022-08-26 21:37:14

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

const int N = 100010;
int fa[N][22], dep[N], d[N];
vector<int> adj[N];
int n, m;

void dfs1(int u, int f) {
    dep[u] = dep[f] + 1;
    
    fa[u][0] = f;
    for (int i = 1; i <= 21; i++) {
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    }

    for (int v : adj[u]) {
        if(v == f) {
            continue;
        }
        dfs1(v, u);
    }
}

int lca(int a, int b) {
    if(dep[a] < dep[b]) swap(a, b);
    for (int i = 21; i >= 0; i--) {
        if(dep[fa[a][i]] >= dep[b]) {
            a = fa[a][i];
        }
    }

    if(a == b) return a;

    for (int i = 21; i >= 0; i--) {
        if(fa[a][i] != fa[b][i]) {
            a = fa[a][i];
            b = fa[b][i];
        }
    }

    return fa[a][0];
}

int ans = 0;
void dfs2(int u, int f) {
    for (int v : adj[u]) {
        if(v == f) {
            continue;
        }
        dfs2(v, u);
        if(d[v] == 0) ans += m;
        else if(d[v] == 1) ans++;
        d[u] += d[v];
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;

    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs1(1, 0);

    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        d[u]++, d[v]++;
        int p = lca(u, v);
        d[p] -= 2;
    }

    dfs2(1, 0);

    cout << ans << "\n";

    return 0;
}

C++14(g++5.4) 解法, 执行用时: 387ms, 内存消耗: 18036K, 提交时间: 2020-01-21 10:56:49

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

const int MAXN = 1e5+1;
int N, M;
vector<int> G[MAXN];
int F[MAXN][20];
int H[MAXN];
int cnt[MAXN];
int tot = 0;

void dfs_lca(int s, int f) {
  F[s][0] = f, H[s] = H[f]+1;
  for (int i = 0; i < 19; i++) F[s][i+1] = F[F[s][i]][i];
  for (auto t: G[s]) if (t != f) dfs_lca(t, s);
}

int lca(int x, int y) {
  if (H[x] < H[y]) swap(x, y);
  for (int i = 19; i >= 0; i--) if (H[F[x][i]] >= H[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];
}
int dfs(int s, int f) {
  int tot = 0;
  for (auto t: G[s]) if (t != f) {
    tot += dfs(t, s);
    cnt[s] += cnt[t];
  }
  if (f == 0) return tot;
  if (cnt[s] == 0) tot += M;
  if (cnt[s] == 1) tot += 1;
  return tot;
}

int main() {
  cin >> N >> M;
  for (int i = 0; i < N-1; i++) {
    int u, v; cin >> u >> v;
    G[u].push_back(v);
    G[v].push_back(u);
  }
  dfs_lca(1, 0);
  for (int i = 0; i < M; i++) {
    int x, y; cin >> x >> y;
    int z = lca(x, y);
    cnt[x]++, cnt[y]++, cnt[z]-=2;
  }
  cout << dfs(1, 0) << endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 427ms, 内存消耗: 18256K, 提交时间: 2020-05-30 21:19:42

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
int N,M;
vector<int> G[MAXN];
int F[MAXN][20];
int H[MAXN];
int cnt[MAXN];
int tot=0;
void dfs_lca(int s,int f)
{
	F[s][0]=f,H[s]=H[f]+1;
	for(int i=0;i<19;i++)
	F[s][i+1]=F[F[s][i]][i];
	for(auto t:G[s])
	if(t!=f)
	dfs_lca(t,s);
}
int lca(int x,int y)
{
	if(H[x]<H[y]) swap(x,y);
	for(int i=19;i>=0;i--)
	if(H[F[x][i]]>=H[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];
}
int dfs(int s,int f)
{
	int tot=0;
	for(auto t:G[s])
	if(t!=f)
	{
		tot+=dfs(t,s);
		cnt[s]+=cnt[t];
	}
	if(f==0) return tot;
	if(cnt[s]==0) tot+=M;
	if(cnt[s]==1) tot+=1;
	return tot;
}
int main()
{
	cin>>N>>M;
	for(int i=0;i<N-1;i++)
	{
		int u,v;
		cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs_lca(1,0);
	for(int i=0;i<M;i++)
	{
		int x,y;
		cin>>x>>y;
		int z=lca(x,y);
		cnt[x]++,cnt[y]++,cnt[z]-=2;
	}
	cout<<dfs(1,0)<<endl;
}

上一题