看到删去一个点,需要剩下的都和关键点连通,有端联想到找点双,因为他怎么删点都是连通的。

对于一个孤立的点双,至少要设两个关键点。

如果两个点双以一个割点连接,假设断掉这个割点,两个块至少要各设一个关键点。类推,所以对于所有含有一个割点的点双,至少要包含非割点的一个关键点。

如果一个点双上有好多个割点,可以不设点,因为把图看成缩掉点双的一棵树,有一个割点的点双一定在叶子处,有多个割点的点双因为有许多树枝,删掉一个,一定可以仍与某一方的叶子(也就是位于叶子处的点双中的关键点)连通,所以不要设。

这样,讨论完毕,统计方案也就很好搞了。

注意一点:孤立点要特判,因为他只要设一个点。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef unsigned long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+;
map<int,int> mp;
struct thxorz{int to,nxt;}G[N];
int Head[N],tot;
int n,m,ans,T;
ll typ;
inline void Addedge(int x,int y){
G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot;
G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot;
}
#define y G[j].to
vector<int> dcc[N];
int dfn[N],low[N],stk[N],cut[N],cnt,rt,Top,dcnt;
void tarjan(int x){
dfn[x]=low[x]=++cnt;int chd=;
if(x==rt&&!Head[x]){dcc[++dcnt].push_back(x);return;}
stk[++Top]=x;
for(register int j=Head[x];j;j=G[j].nxt){
if(!dfn[y]){
++chd;tarjan(y);MIN(low[x],low[y]);//forget MIN...
if(low[y]==dfn[x]){//or low[y]>=dfn[x]
if(x==rt&&chd>=||x^rt)cut[x]=;
int tmp;++dcnt;
do tmp=stk[Top--],dcc[dcnt].push_back(tmp);while(tmp^y);
dcc[dcnt].push_back(x);
}
}
else MIN(low[x],dfn[y]);
}
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
while(read(m),m){
mp.clear();n=ans=;typ=;
memset(Head,,sizeof Head);tot=;
for(register int i=,x,y;i<=m;++i){
read(x),read(y);
if(mp.find(x)==mp.end())mp[x]=++n;
if(mp.find(y)==mp.end())mp[y]=++n;
Addedge(mp[x],mp[y]);
}
memset(dfn,,sizeof dfn),memset(low,,sizeof low),memset(cut,,sizeof cut);dcnt=cnt=;
for(register int i=;i<=n;++i)if(!dfn[i])Top=,rt=i,tarjan(i);
for(register int i=,tt=,siz;i<=dcnt;++i,tt=){
for(register int j=;j<dcc[i].size();++j)if(cut[dcc[i][j]])++tt;
siz=dcc[i].size();
if(siz==)++ans;
else if(!tt)ans+=,typ*=siz*(siz-)/;
else if(tt==)++ans,typ*=(siz-);
dcc[i].clear();
}
printf("Case %d: %d %llu\n",++T,ans,typ);
}
return ;
}

智障WA:line42的MIN漏写了。。果然tarjan还是不熟练啊。

总结:遇到删点和连通性联系在一起的问题时多往点双上想一想,当然凡是点双都要考虑比较特殊的情况,如:2个点,以及孤立点。

BZOJ2730 [HNOI2012]矿场搭建[点双连通分量]的更多相关文章

  1. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Statu ...

  2. [BZOJ2730][HNOI2012]矿场搭建 点双 割点

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2852  Solved: 1344[Submit][Stat ...

  3. bzoj2730 [HNOI2012]矿场搭建 (UVAlive5135 Mining Your Own Business)

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1147  Solved: 528[Submit][Statu ...

  4. [HNOI2012]矿场搭建 (点双连通)

    题目 [HNOI2012]矿场搭建 解析 这个题做的我十分自闭.. 没看出这个是个点双,然后一晚上+半上午.. 一看肯定和割点有关,我们找到所有的点双,会发现有这么几种情况 连通块中一个割点也没有,这 ...

  5. 【双连通分量】Bzoj2730 HNOI2012 矿场搭建

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  6. BZOJ2730:[HNOI2012]矿场搭建(双连通分量)

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  7. bzoj2730矿场搭建——点双连通分量

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2730 首先一遍tarjan找出割点,将图缩点,这些大点中如果有只包含一个割点的,那么如果这个 ...

  8. BZOJ2730——[HNOI2012]矿场搭建

    bzoj2730 & world final 2011 H 1.题目大意:就是有一个无向图,让你在里面选择点,使得,无论哪个点没了以后,其他的点都能到达你选择的任何一个点,输出最少 选择几个点 ...

  9. BZOJ2730 [HNOI2012]矿场搭建 - Tarjan割点

    Solution 输入中没有出现过的矿场点是不用考虑的, 所以不用考虑只有 一个点 的点双联通分量. 要使某个挖矿点倒塌, 相当于割去这个点, 所以我们求一遍割点和点双联通分量. 之后的点双联通分量构 ...

随机推荐

  1. Java学习笔记-抽象类与接口

    抽象类用于在类中不用具体实现,而在子类中去实现的类 抽象类 抽象类概述 抽象定义:抽象就是从多个事物中将共性的,本质的内容抽取出来 抽象类:Java中可以定义没有方法体的方法,该方法的具体实现由子类完 ...

  2. kindeditor 在JSP 中上传文件的配置

    1.将kindeditor,jsp,lib目录下的jar文件放到工程的lib目录下 2.将admin-login.jsp,upload_json.jsp,复制到admin的files目录下 3.复制以 ...

  3. Rocketmq-简单部署

    一.准备环境 1.系统:Centos7.3(无硬性要求) 2. jdk:1.8 3.maven:3.5(无硬性要求) 4.git 5.rocketmq 4.2 二.环境部署 1.jdk1.8以及mav ...

  4. pytorch API中sgd.py的学习记录

    参考:PyTorch与caffe中SGD算法实现的一点小区别 其中公式(3)(4)的符号有问题 变量对应表 程序 参考文章 buf v momentum μ d_p Δf(θ) lr ξ p θ

  5. Hanlp-地名识别调试方法详解

    HanLP收词特别是实体比较多,因此特别容易造成误识别.下边举几个地名误识别的例子,需要指出的是,后边的机构名识别也以地名识别为基础,因此,如果地名识别不准确,也会导致机构名识别不准确. 类型1 数字 ...

  6. go 计算 MD5

    Golang的加密库都放在crypto目录下,其中MD5库在crypto/md5包中,该包主要提供了New和Sum函数 直接调用md5计算 package main import ( "cr ...

  7. SQL SERVER MONTH函数

    定义: MONTH函数返回指定日期的月的部分 语法: MONTH(date) 参数: ①date参数是合法的日期表达式. 返回值: int型数据 例:  声明:本文是本人查阅网上及书籍等各种资料,再加 ...

  8. LeetCode. 位1的个数

    题目要求: 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例: 输入:00000000000000000000000000001011 输 ...

  9. 网络流+最小生成树的最少割边数--How Many to Be Happy?

    题意:https://blog.csdn.net/Ratina/article/details/95200594 思路: 首先我们知道最小生成树就是按长度枚举边,能连就连. 那么,如果这条边在最小生成 ...

  10. redis快速开始

    1 下载地址:http://redis.io/download 2 安装步骤: 3 # 安装gcc 4 yum install gcc 5 6 # 把下载好的redis‐5.0.3.tar.gz放在/ ...