[POI2008]BLO-Blockade 题解

poi~



原题目

点无非分为两种

割点 & 非割点

根据题目可得 , 对于非割点答案显然是

ans = (n - 1) * 2;

那么对于割点怎么处理答案呐?

把她分成两部分处理

对于一个点 fa

他的所有子树(搜索树中)的 size 互相乘起来 , 因为子树间互相断开不能联系

然后把所有子树的 size 加起来得 sum , 然后 ans += sum * (n - sum - 1) , 因为所有的子树都无法与外界联系

因为不算 fa 本身 , 所以是 (n - sum - 1) 而非 (n - sum)

但是对于一个点对 (a, b) 断开了显然有 (b, a) 也断开

我们只处理了一个 , 所以最后要把答案乘二

最后对于割点也要再加上 (n - 1) * 2 来处理上文没有处理的 fa 的情况



至于怎么得到 size , 在tarjan处理割点的时候处理一下就可以了

代码:

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define APART puts("----------------------")
  8 #define debug 1
  9 #define FILETEST 1
 10 #define inf 500010
 11 #define ll long long
 12 #define ha 998244353
 13 #define INF 0x7fffffff
 14 #define INF_T 9223372036854775807
 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 16
 17 namespace chino{
 18
 19 inline void setting(){
 20 #if FILETEST
 21     freopen("_test.in", "r", stdin);
 22     freopen("_test.me.out", "w", stdout);
 23 #endif
 24     return;
 25 }
 26
 27 inline int read(){
 28     char c = getchar(), up = c; int num = 0;
 29     for(; c < ‘0‘ || c > ‘9‘; up = c, c = getchar());
 30     for(; c >= ‘0‘ && c <= ‘9‘; num = (num << 3) + (num << 1) + (c ^ ‘0‘), c = getchar());
 31     return  up == ‘-‘ ? -num : num;
 32 }
 33
 34 int n, m;
 35 int cntJ, cntE;
 36 int cut[inf], size[inf];
 37 ll ans[inf];
 38 int dfn[inf], low[inf];
 39 int head[inf];
 40 struct Edge{
 41     int to;
 42     int next;
 43 }e[inf << 1];
 44
 45 inline void AddEdge(int from, int to){
 46     ++cntE;
 47     e[cntE].to = to;
 48     e[cntE].next = head[from];
 49     head[from] = cntE;
 50     return;
 51 }
 52
 53 void tarjan(int now, int root){
 54     dfn[now] = low[now] = ++cntJ;
 55     int index = 0, sum = 0;
 56     size[now] = 1;
 57     for(int i = head[now]; i; i = e[i].next){
 58         int to = e[i].to;
 59         if(dfn[to] == 0){
 60             tarjan(to, 0);
 61             low[now] = std::min(low[now], low[to]);
 62             size[now] += size[to];
 63             if(root)
 64                 ++index;
 65             if(low[to] >= dfn[now]){
 66                 if(root == 0)
 67                     cut[now] = 1;
 68                 ans[now] += 1ll * size[to] * sum;
 69                 sum += size[to];
 70             }
 71         } else
 72             low[now] = std::min(low[now], dfn[to]);
 73     }
 74     if(root && index >= 2)
 75         cut[now] = 1;
 76     ans[now] += 1ll * sum * (n - sum - 1);
 77     return;
 78 }
 79
 80 inline int main(){
 81     n = read();
 82     m = read();
 83     for(int i = 1; i <= m; i++){
 84         int u = read();
 85         int v = read();
 86         AddEdge(u, v);
 87         AddEdge(v, u);
 88     }
 89     for(int i = 1; i <= n; i++){
 90         if(dfn[i] == 0)
 91             tarjan(i, 1);
 92     }
 93     for(int i = 1; i <= n; i++){
 94         if(cut[i] == 0)
 95             ans[i] = 0;
 96         ans[i] += n - 1;
 97         ans[i] <<= 1;
 98         printf("%lld\n", ans[i]);
 99     }
100     return 0;
101 }
102
103 }//namespace chino
104
105 int main(){return chino::main();}

最后瞎说几句(小声bb)

自己一开始想了个假做法结果做了好长时间zbl

原文地址:https://www.cnblogs.com/chiarochinoful/p/problem-poi2008-BLO-Blockade.html

时间: 2024-10-09 22:34:23

[POI2008]BLO-Blockade 题解的相关文章

BZOJ1123: [POI2008]BLO

1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 614  Solved: 235[Submit][Status] Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数,代表如果把第i个点去掉,将有多

1123: [POI2008]BLO

1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MB链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1123 Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数

BZOJ 1123: [POI2008]BLO

1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1030  Solved: 440[Submit][Status][Discuss] Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数,代表如果把

[POI2008]BLO

1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1519  Solved: 697[Submit][Status][Discuss] Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数,代表如果把

[POI2008]枪战Maf题解

问题 C: [POI2008]枪战Maf 时间限制: 1 Sec  内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的人也不同. 输入 输入n人数<1000000 每个人的aim 输出 你要求最后死亡数目的最小和最大可能 样例输入 8 2 3 2 2 6 7 8 5 样例输出 3 5 本次考试最后一个题,被老师评论称难炸了--然而貌似不那么难,但你

【dfs+连通分量】Bzoj1123 POI2008 BLO

Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数,代表如果把第i个点去掉,将有多少对点不能互通. Solution 求割顶的一系列操作不仅可以用来求割顶,也可以解决很多问题,比如这道题. dfs是很神奇的,对于节点u能扩展出去的v的子树是互相独立的,反向边也只会往上连. 那么对于

bzoj1123: [POI2008]BLO(割点)

bzoj1123 题目描述:给定n个城市,m条边,每条边连接两个不同的城市,没有重复的路,所有的城市相连. 输入格式:输入n<=100000 m<=500000 及 m 条边 输出格式:输出 n 个数,代表如果把第 i 个点去掉,将有多少对点不能互通. 输入样例: 5 5 1 2 2 3 1 3 3 4 4 5 输出样例: 8 8 16 14 8 解析:把每个点去掉,对答案的贡献就是每个被分割出的联通块的的大小之积 + (n - 1) 再乘2 ???关键在于如何快速求出每个联通块的大小. ??

【BZOJ-1123】BLO Tarjan 点双连通分量

1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 970  Solved: 408[Submit][Status][Discuss] Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n<=100000 m<=500000及m条边 Output 输出n个数,代表如果把第

tarjan

首先还是说明这是一个坑 然后tarjan以前一直处于懵懵懂懂的状态,决定痛改前非好好学. tarjan可以用来求强联通分离. 它有两个数组,一个是dfn,一个是low. 定义DFN(u)为节点u搜索的次序编号(时间戳).Low(u)为u或者u的子树能够追溯到的最早的栈中的节点的次序号. 然后就发现u的儿子无非三种情况:一是还没访问过,然后是访问过而且已经在某个强联通分量里面,最好是访问过但是还在栈里面. 对于第一种情况就直接访问 然后low[u]=min(low[u],low[son]) 对于第

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734