http://acm.timus.ru/problem.aspx?space=1&num=1557

1557. Network Attack

Time limit: 2.0 second
Memory limit: 64 MB
In some computer company, Mouse Inc., there is very complicated network structure. There are a lot of branches in different countries, so the only way to communicate with each other is the Internet. And it's worth to say that interaction is the key to the popularity and success of the Mouse Inc.
The CEO of this company is interested now to figure out whether there is a way to attack and devastate whole structure. Only two hackers are capable to perpetrate such an outrage — Vasya and Petya, who can destroy any two channels. If after that there are at least two servers without connection between them, then they succeed.
In other words, the company is a set of servers, some of them connected with bidirectional channels. It's guaranteed that all the servers are connected directly or indirectly. The hackers' goal is to divide network into at least two parts without any connection between them. Each hacker can destroy exactly one channel. And they can't destroy the same channel together. You are asked to count the number of ways for hackers to win.

Input

There are two integer numbers (NM) in the first line of input: the number of servers and channels respectively (1 ≤ N ≤ 2000; 0 ≤ M ≤ 100000). In the each of the next M lines there are exactly two numbers — the indices of servers connected by channel. Channels can connect a server to itself. There can be multiple channels between one pair of servers. The servers are numbered from 1 to N.

Output

There must be exactly one integer — the answer to the question described in the problem.

Sample

input output
3 3
1 2
2 3
3 1
3
Problem Source: Novosibirsk SU Contest. Petrozavodsk training camp, September 2007
 
思路:
首先dfs建树,这个时候图就只分为树边和回边,自边(回边+自边=非树边),(没有横边),分隔方案有三种
1:拆除的一条边是桥,另外一条随便,这个用tarjian算法解决,设桥的数量为nb,总边数m,则第一类方案数为(m-nb)*nb+nb*(nb-1)/2
2:拆除两条边后分离出了一棵子树,这时候一定一条边是树边(肯定不是桥边),另外一条是回边,只需要统计一下,设b[s]存储以s为顶点的子树到s的祖先的边数,b[s]==2就有一种方案
3:拆除两条边后分离出了子树的一部分,如图:
分出中间那部分,剩下两部分可以相连,
这就要求中间部分到上面部分(祖先)和下面部分(分出来的子树)间都没有边相连,
明显,毁坏的必须是两条树边,而且不是桥边(需要b[s]>1,b[son]>1)
记录深度数组dfn[],分出来的子树的回边所能到达的最低深度为high[]数组,那么当我们确定要毁坏的是s和父亲的树边时,需要搜寻s有没有满足条件的配对点son来破坏son和其父亲间的树边使得中间部分脱离,此时必须有high[son]<dfn[s],使得上面部分到中间部分没有边,下面部分到中间部分也没有边.
但是注意,中间部分可能有内部的回边,所以要控制b[s]==b[son],使得b[son]和b[s]之间没有未被接收的回边
 
 感想:这题思路似乎很简单,但是一开始考虑的是,设由祖先向节点s的子树连所连的最浅子节点深度为high[s](通过非树边),则第三类点一定在这个点上面,但是这样做的话,无法规避这种情况
于是,再设一个条件,第三类合格点要满足其深度大于"深度大于s节点的祖先"(s的儿子,合格点的祖先)所能连到的最深深度,不过还是不能过Test#16
最后还是直接使用了上交红书的方法
 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=2002,maxm=200002;//ATTENTION,undirect
int n,m;
ll ans,nb; int b[maxn];
int c[maxn];//edge to its father,select and acceed int first[maxn];
int next[maxm];
bool tree[maxm];
int to[maxm];
int brg[maxm];//bridge int dfn[maxn],high[maxn],depth;
bool up[maxn][maxn]; void dfs(int s,int aim){
for(int p=first[s];p!=-1;p=next[p]){
if(tree[p]){
dfs(to[p],aim);
}
}
if(c[s]==1&&b[s]==b[aim]&&high[s]<dfn[aim]){
// printf("b:%d %d\n",aim,s);
ans++;
}
// return ans;
} void addedge(int f,int t,int ind){
next[ind]=first[f];
first[f]=ind;
to[ind]=t;
swap(f,t);ind++;
next[ind]=first[f];
first[f]=ind;
to[ind]=t;
}
void tarjan(int s,int pf){
dfn[s]=++depth;
for(int p=first[s];p!=-1;p=next[p]){
if(s==to[p]){continue;}
if(pf>=0&&to[p]==to[pf^1])c[s]++;
if((p|1)==(pf|1)){b[s]++;continue;} if(dfn[to[p]]==0){
tree[p]=true; tarjan(to[p],p);
if(b[to[p]]==1){
brg[nb++]=p;
}
b[s]+=b[to[p]]-1; for(int i=1;i<=dfn[s];i++){
if(up[to[p]][i])up[s][i]=true;
}
}
else {
if(dfn[to[p]]>dfn[s]){
b[s]--;
}
else {
up[s][dfn[to[p]]]=true;
b[s]++;
}
}
} high[s]=dfn[to[pf^1]];
for(int i=dfn[to[pf^1]];i>=0;i--){
if(up[s][i]){high[s]=i;break;}
} if(b[s]==2)ans++;
if(c[s]==1&&b[s]>1){
for(int p=first[s];p!=-1;p=next[p]){
if(tree[p]){
dfs(to[p],s);
}
}
}
} int main(){
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
for(int i=0;i<m;i++){
int f,t;
scanf("%d%d",&f,&t);
addedge(f,t,2*i);
} tarjan(1,-1); ans+=(m-nb)*nb+nb*(nb-1)/2;
printf("%I64d\n",ans); return 0;
}

  

URAL 1557 Network Attack 图论,连通性,tarjain,dfs建树,分类讨论 难度:2的更多相关文章

  1. Network Attack

    Network Attack Nicola regularly inspects the local networks for security issues. He uses a smart and ...

  2. URAL 1141. RSA Attack RSA加密演算法

    标题来源:URAL 1141. RSA Attack 意甲冠军:给你e n c 并有m^e = c(mod n) 求 m 思路:首先学习RSA算法 here 过程大致是 1.发送的信息是m 2.随机选 ...

  3. D. New Year Santa Network 解析(思維、DFS、組合、樹狀DP)

    Codeforce 500 D. New Year Santa Network 解析(思維.DFS.組合.樹狀DP) 今天我們來看看CF500D 題目連結 題目 給你一棵有邊權的樹,求現在隨機取\(3 ...

  4. 【树链剖分】【dfs序】【LCA】【分类讨论】Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground

    一棵树,q次询问,每次给你三个点a b c,让你把它们选做s f t,问你把s到f +1后,询问f到t的和,然后可能的最大值是多少. 最无脑的想法是链剖线段树……但是会TLE. LCT一样无脑,但是少 ...

  5. HDU - 3974 Assign the task (DFS建树+区间覆盖+单点查询)

    题意:一共有n名员工, n-1条关系, 每次给一个人分配任务的时候,(如果他有)给他的所有下属也分配这个任务, 下属的下属也算自己的下属, 每次查询的时候都输出这个人最新的任务(如果他有), 没有就输 ...

  6. Network POJ - 3417(LCA+dfs)

    Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried because she has jus ...

  7. 图论算法之DFS与BFS

    概述(总) DFS是算法中图论部分中最基本的算法之一.对于算法入门者而言,这是一个必须掌握的基本算法.它的算法思想可以运用在很多地方,利用它可以解决很多实际问题,但是深入掌握其原理是我们灵活运用它的关 ...

  8. URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)

    题目链接: URAL 1890 . Money out of Thin Air 题目描述: 给出一个公司里面上司和下级的附属关系,还有每一个人的工资,然后有两种询问: 1:employee x y z ...

  9. URAL 1160 Network(最小生成树)

    Network Time limit: 1.0 secondMemory limit: 64 MB Andrew is working as system administrator and is p ...

随机推荐

  1. 2018.9 ECNU ICPC/CCPC Trial Round #2 Query On Tree (树链剖分+线段树维护)

    传送门:https://acm.ecnu.edu.cn/contest/105/problem/Q/ 一棵树,支持两种操作:给一条路径上的节点加上一个等差数列;求两点路径上节点和. 很明显,熟练剖分. ...

  2. 【Q2D】 2048设计

    主要组件 1: GameDirector ,负责胜利.失败.载入上次成绩等 2: Grid, 表格类,负责管理tile二维数组 3: Tile 元素类,就是界面上移动的砖块了 4: InputHelp ...

  3. 论文笔记:蒸馏网络(Distilling the Knowledge in Neural Network)

    Distilling the Knowledge in Neural Network Geoffrey Hinton, Oriol Vinyals, Jeff Dean preprint arXiv: ...

  4. ajax的认识

    1. ajax是一种技术,无需刷新页面即可向服务器传输.读写数据. 2. ajax的参数说明: 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为 ...

  5. python、pip、whl安装和使用

    1 python的安装 首先,从python的官方网站 www.python.org下载需要的python版本,地址是这个: http://www.python.org/ftp/python/2.7. ...

  6. ABP官方文档翻译 1.3 模块系统

    ABP模块系统 介绍 模块定义 生命周期方法 PreInitialize Initialize PostInitialize Shutdown 模块依赖 插件系统 ASP.NET Core ASP.N ...

  7. LINUX SHELL 笔记 01: 脚本

    root@iZwz:~/labs# vim myfirst root@iZwz:~/labs# cat myfirst #!/bin/bash clear echo "this is my ...

  8. GIT使用—补丁与钩子

    一.补丁 生成补丁 [root@localhost buding]# echo B > file;git add file;git commit -m "B" [master ...

  9. 20145321 《Java程序设计》第一周学习总结

    20145321 <Java程序设计>第1周学习总结 教材学习内容总结 第一章 1.三大平台:Java SE.Java EE .Java ME 2.Java SE:由JVM.JRE.JDK ...

  10. java第四周学习总结

    学号20145336 <Java程序设计>第4周学习总结 教材学习内容总结 继承 继承符合(Don't Repeat Yourself)原则,即在自己的代码中不要重复自己编写的信息,这在多 ...