hdu4587 Two Nodes 求图中删除两个结点剩余的连通分量的数量
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4587
题目给了12000ms,对于tarjan这种O(|V|+|E|)复杂度的算法来说,暴力是能狗住的。可以对每个点进行枚举,然后对剩余的网络进行tarjan,对割点所能造成的最大的连通分量进行查询,也就是如下的方程。ans=max{cut[i]}+cnt 其中cnt删除第一个结点之后剩下的网络在初始时刻的连通分量的数量,也就是对每一个第一结点tarjan进行深搜的次数。另外,这次的tarjan中的cut数组存储的不再是这个点是否是割点,而是这个点“成为割点的次数”,也就是说,对于一个非根节点u来说,他有k个分支只能通过u来连接到u的祖先,所以u被删除之后就会多出来k个连通分量,这个cut的更新是在搜索完一个分支之后退回到u时更新的。对于根节点来说,由于他没有父结点,原先他所在的连通分量的分量数量为1,现在把它割掉,还剩k个子树的连通分量,也就是根节点使得连通分量的数量增加了k-1,这是不同于非根节点的。
注意根节点能增加的连通分量的数量的更新方式!对于根节点删除能增加多少子连通图数量,只要判断是不是父节点就可以,不应判断子树的数量,因为如果子树的数量大于1的话增加的连通块数量是child-1,当这个点是孤立点的时候删除这个结点的话连通块的数量实际上是减少的!!!!
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a))
#define prime1 1e9+7
#define prime2 1e9+9
#define pi 3.14159265
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define scand(x) scanf("%llf",&x)
#define f(i,a,b) for(int i=a;i<=b;i++)
#define scan(a) scanf("%d",&a)
#define mp(a,b) make_pair((a),(b))
#define P pair<int,int>
#define dbg(args) cout<<#args<<":"<<args<<endl;
#define inf 0x3f3f3f3f
const int maxn=;
const int maxm=;
int n,m,t;
int head[maxn],nxt[maxm],cut[maxn],dfn[maxn],low[maxn];
struct node{
int u,v;
}p[maxm];
int e;
int first;
int id;
void addedge(int u,int v)
{
p[e].u=u;
p[e].v=v;
nxt[e]=head[u];
head[u]=e++;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++id;
int child=;
for(int i=head[u];~i;i=nxt[i])
{
int v=p[i].v;
if(v==first||v==fa)continue;//假定了这个网络中没有first结点
if(!dfn[v])
{
child++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&u!=fa)cut[u]++;//非根结点成为割点,可割的连通分量的数量增加
}
else if(dfn[v]<dfn[u]&&v!=fa)
{
low[u]=min(low[u],dfn[v]);
}
}
//下面这句更新方法是错误的,因为当儿子结点的个数是0的时候这个点就是孤立点,如果把它删去连通分量的数量会减少1!!!!!
// if(u==fa&&child>=1)cut[u]=child-1;
if(u==fa&&child>=)cut[u]=child-; //更新根节点的cut值的唯一方法是通过子树的数量-1
//注意此时如果根节点的child值是1的话更新之后是0,所以不能加child>1的条件
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
std::ios::sync_with_stdio(false);
while(scanf("%d%d",&n,&m)!=EOF)
{
int x,y;
f(i,,maxn-)head[i]=-,nxt[i]=-;
e=;
f(i,,m)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
int curnum;
int ans=;
f(i,,n-)//枚举每一个点,再用tarjan对割点进行查找,找到割点增加连通分量最多的点。
{
f(j,,n-)dfn[j]=,cut[j]=;//要进行n次对这个网络的tarjan,每次都要清零
first=i;
curnum=;
id=;
f(j,,n-)
{
if(i==j)continue;
if(!dfn[j])
{
tarjan(j,j);
curnum++;
}
}
f(j,,n-)
{
if(j!=i) ans=max(ans,curnum+cut[j]);
}
}
pf("%d\n",ans);
}
return ;
}
hdu4587 Two Nodes 求图中删除两个结点剩余的连通分量的数量的更多相关文章
- [Swift]LeetCode882. 细分图中的可到达结点 | Reachable Nodes In Subdivided Graph
Starting with an undirected graph (the "original graph") with nodes from 0 to N-1, subdivi ...
- Floyd-Warshall求图中任意两点的最短路径
原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短 ...
- 用C语言把双向链表中的两个结点交换位置,考虑各种边界问题。
用C语言把双向链表中的两个结点交换位置,考虑各种边界问题. [参考] http://blog.csdn.net/silangquan/article/details/18051675
- [LeetCode] 882. Reachable Nodes In Subdivided Graph 细分图中的可到达结点
Starting with an undirected graph (the "original graph") with nodes from 0 to N-1, subdivi ...
- [LintCode] Swap Two Nodes in Linked List 交换链表中的两个结点
Given a linked list and two values v1 and v2. Swap the two nodes in the linked list with values v1 a ...
- 求二叉树中第K层结点的个数
一,问题描述 构建一棵二叉树(不一定是二叉查找树),求出该二叉树中第K层中的结点个数(根结点为第0层) 二,二叉树的构建 定义一个BinaryTree类来表示二叉树,二叉树BinaryTree 又是由 ...
- hdu 5952 Counting Cliques 求图中指定大小的团的个数 暴搜
题目链接 题意 给定一个\(n个点,m条边\)的无向图,找出其中大小为\(s\)的完全图个数\((n\leq 100,m\leq 1000,s\leq 10)\). 思路 暴搜. 搜索的时候判断要加进 ...
- poj The Settlers of Catan( 求图中的最长路 小数据量 暴力dfs搜索(递归回溯))
The Settlers of Catan Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1123 Accepted: ...
- 083 Remove Duplicates from Sorted List 有序链表中删除重复的结点
给定一个排序链表,删除所有重复的元素使得每个元素只留下一个.案例:给定 1->1->2,返回 1->2给定 1->1->2->3->3,返回 1->2- ...
随机推荐
- Promise 的含义
Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Pro ...
- 从头认识js-函数表达式
定义函数的方式有两种: 1.函数声明(特征:函数声明提升,在执行代码之前会先读取函数声明,这就意味着可以把函数声明放在调用它的语句之后) 2.函数表达式(函数表达式与其他表达式一样,使用之前必须先声明 ...
- 深度学习遥感影像(哨兵2A/B)超分辨率
这段时间,用到了哨兵影像,遇到了一个问题,就是哨兵影像,它的RGB/NIR波段是10米分辨率的,但是其他波段是20米和60米的,这就需要pansharpening了,所以我们需要设计一种算法来进行解决 ...
- 基于abp框架的数据库种子数据初始化
目录 基于abp框架的数据库种子数据初始化 1.背景 2.参照 3.解决方案 3.1 初始化数据 3.2 依赖注入方法容器里获取数据库上下文 3.3 封装创建初始化数据列表方法 3.4 数据库中没有的 ...
- 使用web写UI, 使用js对接C++项目, 提高开发效率
ppt资源下载地址https://www.slidestalk.com/s/webui_nodejs_cmdlrx
- 通读Python官方文档之cgitb
cgitb CGI脚本异常管理 源代码:Lib/cgitb.py cgitb模块为Python脚本提供了一个特殊的异常管理器.名字有点误导人,它最初设计是为了以HTML格式展示cgi脚本的大量异常信息 ...
- Ubuntu中VMware tools的安装步骤
按照下面的步骤,轻松解决!! 1.点击导航栏中的虚拟机,下面的安装VMware tools 2.点击桌面上的光盘,进入后,将tar.gz文件复制到桌面,然后右击提取到此处: 3.在桌面打开终端,cd到 ...
- VUE实现Studio管理后台(十):OptionBox,一个综合属性输入界面,可以级联重置
为了便于阅读代码,已经把测试数据分离出来,放在了mock目录下: 阅读代码的话,稍微留意一下就好.本次介绍RXEditor界面最重要的部分,属性输入组件,该组件可以显示是否有数据被修改,还可以批量重置 ...
- Yuchuan_Linux_C编程之九目录操作相关函数
一.整体大纲 二.相关函数 1. getcwd 函数作用:获取当前目录 头文件 #include <unistd.h> 函数原型 char *getcwd(char *buf, size_ ...
- Rust入坑指南:智能指针
在了解了Rust中的所有权.所有权借用.生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟. 智能指针是Rust中一种特殊的数 ...