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. Spring-1-E Game(HDU 5011)解题报告及测试数据

    Game Time Limit:1000MS     Memory Limit:65536KB Description Here is a game for two players. The rule ...

  2. SpringBoot Web项目中中如何使用Junit

    Junit这种老技术,现在又拿出来说,不为别的,某种程度上来说,更是为了要说明它在项目中的重要性. 凭本人的感觉和经验来说,在项目中完全按标准都写Junit用例覆盖大部分业务代码的,应该不会超过一半. ...

  3. 在eclipse中new 对象后怎么通过快捷键自动生成返回对象

    如题,每次new 对象的时候不想手动补全返回对象,可以实现快捷键生成返回对象.new  对象后可以按住ctrl+1,如下图: 选择第一行即可.

  4. input 虚拟键盘

    if (!Element.prototype.scrollIntoViewIfNeeded) { Element.prototype.scrollIntoViewIfNeeded = function ...

  5. “使用驱动器中J:的光盘之前需要将其格式化

    不知道神马原因致使U盘无法打开——大家千万注意:以后遇见这种情况千万别格式化(当然如果你的U盘或者硬盘里没有重要东西那就另当别论),进入“开始-cmd”,因为我的U盘在电脑上读出来是J盘,所以在cmd ...

  6. 自制Linux映像和发行版Robomind

    通常ARM开发板厂商会提供已编译好的Linux映像供用户使用.我手上的MarS Board的厂商提供了Ubuntu映像,只是版本有点老,文件系统也比较大.之前我已经移植了较新的Linux内核,现在我想 ...

  7. Django学习笔记之Django的url反向解析

    0x00 URL反向解析和三种不同的反向解析方式 Django中提供了关于URL的映射的解决方案,可以做两个方向的使用: 1.普通解析过程:由客户端的浏览器发起一个url请求,Django根据URL解 ...

  8. CentOS的Qt3和Qt4问题

    在有的系统中,装有Qt3和Qt4, 在使用qmake生成Makefile后,直接make, 出错,说没有头文件, 如果调用了qt3的qmake,那么上头的INCPATH里的头文件路径也指向了Qt3, ...

  9. unicode下数据之间的转换

    首先mfc下字符串只有两种数据:char(一个字节)和wchar_t(两个字节),很多其他数据类型如TCHAR,WCHAR等都是这个两个基本类型的宏定义,BYTE是uchar 1.对话框打印char* ...

  10. springboot集成shiro 前后端分离 统一处理shiro异常

    在前后端分离的情况下,shiro一些权限异常处理会返回401之类的结果,这种结果不好统一管理.我们希望的结果是统一管理,所有情况都受我们控制 就算权限验证失败,我们也希望返回200,并且返回我们定义的 ...