首页 > 其他分享 >暗的连锁 题解

暗的连锁 题解

时间:2023-04-22 12:01:17浏览次数:44  
标签:dep int 题解 附加 Dark fa MAXN 连锁

题目描述

Dark 是一个无向图,图中有 \(n\) 个结点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark 有 \(n-1\) 条主要边,并且 Dark 的任意两个结点之间都存在一条只由主要边构成的路径。另外,Dark 还有 \(m\) 条附加边。

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

注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断一条附加边才算击败了 Dark。

数据范围:\(1\le n\le 10^5, 1\le m\le 2\times 10^5\)。

题解

考虑枚举第一次删掉的边是哪一条。显然这个东西最开始是一个树,每次添加一条附加边就会多加入一个环。

对于一条原先的树边,如果它不被任何一个环所包含,那么砍掉它就会将 Dark 直接分为两半,此时任意再切一个附加边即可,对答案的贡献是 \(m\)。若这条树边被一个环所包含(也就是这条边是某个环的组成部分),那么切了它就只能再切那条相应附加边,对答案的贡献是 \(1\),若被两个或以上的包含,那么切这条边就没有任何用处。

暴力的做法是 \(O(n^2)\) 的,时间复杂度卡在了统计每条树边被几个环所包含。

比如这个图,若在 6 与 3 之间加上了一条附加边,则会形成一个 \(2-3-6-5\) 的环,发现这个环其实最高只影响到了 \(\operatorname{LCA}(u,v)\),于是考虑树上差分,对于每条附加边 \(u,v\),使得 \(d_u,d_v\) 都增加 \(1\),\(d_{\operatorname{LCA}(u,v)}\) 减 \(2\)。最后统计一下即可。

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

const int MAXN = 1e5 + 5;
int n, m, d[MAXN], dep[MAXN], fa[MAXN][32], ans[MAXN], anss;
vector<int> G[MAXN];

void predfs(int x, int fat) {
  fa[x][0] = fat;
  dep[x] = dep[fat] + 1;
  for (auto u : G[x]) {
    if (u == fat) continue;
    predfs(u, x);
  }
}

int LCA(int u, int v) {
  if (dep[u] < dep[v]) swap(u, v);
  for (int i = 29; i >= 0; --i) {
    if (dep[fa[u][i]] >= dep[v]) u = fa[u][i];
  }
  if (u == v) return v;
  for (int i = 29; i >= 0; --i) {
    if (fa[u][i] != fa[v][i]) {
      u = fa[u][i], v = fa[v][i];
    }
  }
  return fa[u][0];
}

void dfs(int x, int fat) {
  ans[x] = d[x];
  for (auto u : G[x]) {
    if (u == fat) continue;
    dfs(u, x);
    ans[x] += ans[u];
  }
}

int main(void) {
  cin >> n >> m;
  for (int i = 1; i < n; ++i) {
    int u, v;
    cin >> u >> v;
    G[u].push_back(v);
    G[v].push_back(u);
  }
  // LCA Init
  predfs(1, 0);
  for (int i = 1; i < 30; ++i) {
    for (int j = 1; j <= n; ++j) {
      fa[j][i] = fa[fa[j][i - 1]][i - 1];
    }
  }
  // Calculate Answer
  for (int i = 1; i <= m; ++i) {
    int u, v;
    cin >> u >> v;
    d[u]++, d[v]++, d[LCA(u, v)] -= 2;
  }
  dfs(1, 0);
  for (int i = 2; i <= n; ++i) {
    if (ans[i] == 0)
      anss += m;
    else if (ans[i] == 1)
      anss++;
  }
  cout << anss << endl;
  return 0;
}

标签:dep,int,题解,附加,Dark,fa,MAXN,连锁
From: https://www.cnblogs.com/XiaoQuQu/p/17342715.html

相关文章

  • ABC298E 题解
    前言题目传送门!更好的阅读体验?题解区的代码都好丑啊,嘲讽。思路对于这种概率题,正常人都能反应到这是dp。所以:\(dp_{t,i,j}\)表示:当前是第\(t\)回合,Tak在\(i\)位置,Aok在\(j\)位置,概率。如果这样设状态的话,转移方程就会非常一眼(刷表):\[dp_{t,\min(i+\texttt{st......
  • [P8766 [蓝桥杯 2021 国 AB] 异或三角]题解
    P8766[蓝桥杯2021国AB]异或三角题目描述分析题目中给出了三个限制首先我们不妨设\(a,b\ltc\),则而由于我们把\(c\)作为了最大值,原题需要有序对\((a,b,c)\)所以\(ans\ast3\)1.\(1\leqa,b,c\leqn\)2.\(a\oplusb\oplusc=0\)3.\(a+b\gtc\)而在枚举过程中,......
  • P1350 车的放置 题解
    一、题目描述:给你一个网格棋盘,a,b,c,d 表示了对应边长度,也就是对应格子数。例如,当a=b=c=d=2时,对应如下面这样一个棋盘:想要在这个棋盘上放 k棋子,也就是这 k 个棋子没有两个在同一行,也没有两个在同一列,问有多少种方案。数据保证 0......
  • [ARC138D] Differ by K bits 题解
    小清新构造题。首先\(K=1\)的情况是trival的,直接格雷码即可。对于\(K>1\),我们发现题目的约束相当于\(\operatorname{popcount}(P_i\oplusP_{(i+1)\bmod2^N})=K\),考虑\(P_i\)的差分序列\(D_i\),那么\(D_i\)一定是一个恰好有\(K\)位\(1\)的二进制数,记\(S=\{i\mid......
  • 团体程序设计天梯赛 L1-064 估值一亿的AI核心代码 题解
    思路L1-064估值一亿的AI核心代码题意有一点不太清晰的,就是原文中的'I',无论是否是单独的,都不能变为小写。如果是单独的'I'再被转化为'you'。这种模拟题就需要每个的分分清清楚楚的,不要都揉到一块儿,容易写错。具体还有些需要注意的在代码里注释着了。代码#include<iostream>......
  • Android Studio Gradle Download 慢/卡问题解决
    build.gradlebuildscript{repositories{//jcenter()//jcenter(){url'http://jcenter.bintray.com/'}maven{url'http://maven.aliyun.com/nexus/content/groups/public/'}maven{url"https://jitpac......
  • 【题解】P4069 [SDOI2016]游戏
    题目描述Alice和Bob在玩一个游戏。游戏在一棵有\(n\)个点的树上进行。最初,每个点上都只有一个数字,那个数字是\(123456789123456789\)。有时,Alice会选择一条从\(s\)到\(t\)的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点\(r\),若\(r\)与\(s\)......
  • 【题解】P5327 [ZJOI2019] 语言
    P5327[ZJOI2019]语言题目描述九条可怜是一个喜欢规律的女孩子。按照规律,第二题应该是一道和数据结构有关的题。在一个遥远的国度,有\(n\)个城市。城市之间有\(n-1\)条双向道路,这些道路保证了任何两个城市之间都能直接或者间接地到达。在上古时代,这\(n\)个城市之间处......
  • Android问题解决:android.os.FileUriExposedException: file:///storage/......Intent.
    文章目录一、遇到问题二、解决问题三、分析问题一、遇到问题---------beginningofcrash2022-12-2720:18:15.01014422-14422/com.lisi.evidence_boxE/AndroidRuntime:FATALEXCEPTION:mainProcess:com.lisi.evidence_box,PID:14422android.os.FileUriExpose......
  • 2022年中国大学生程序设计竞赛女生专场-比赛题解
    比赛链接:Dashboard-2022年中国大学生程序设计竞赛女生专场-CodeforcesA.减肥计划(模拟)模拟,如果队列第一个人体重是最大的了,则这个人的位置不会再变,直接输出即可。#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ios::sync_with_......