bzoj 2730 割点
首先我们知道,对于这张图,我们可以枚举坍塌的是哪个点,对于每个坍塌的点,最多可以将图分成若干个不连通的块,这样每个块我们可能需要一个出口才能满足题目的要求,枚举每个坍塌的点显然是没有意义的,我们只需要每个图的若干个割点,这样除去割点的图有若干个块,我们可以求出只与一个割点相连的块,这些块必须要一个出口才能满足题目的要求,每个块内有块内个数种选法,然后将所有满足一个割点相连的块的点数连乘就行了。
对于每个与一个割点相连的块必须建出口可以换一种方式理解,我们将每个块看做一个点,那么算上割点之后,这张图就变成了一颗树,只有叶子节点我们需要建立出口,因为对于非叶子节点我们不论断掉哪个点我们都有另一种方式相连,这里的叶子节点就是与一个割点相连的块。
最后还有个特判,就是对于一个双连通图,我们至少需要选取两个点作为出口,因为如果就选一个,可能该点为坍塌点,这时我们就任选两个点就行了,方案数为点数*(点数-1)>>1。
反思:最开始的时候求只与一个割点相连的块的计算的时候割点计算重复了,后来没有割点的时候的特判没有加,最后的时候发现这道题需要开long long,开了之后忘记改输出的通配符,改了之后输出2的时候应该是2ll,对C++的使用还不够熟悉。
/**************************************************************
Problem: 2730
User: BLADEVIL
Language: C++
Result: Accepted
Time:40 ms
Memory:2956 kb
****************************************************************/ //By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 50010 using namespace std; int n;
int last[maxn],pre[maxn],other[maxn];
int dfn[maxn],low[maxn],cut[maxn],vis[maxn],size[maxn],num[maxn],flag[maxn],fuck[maxn];
int l,time;
long long ans1,ans2,task; void getmin(int &x,int y)
{if (y<x) x=y;}
void connect(int x,int y)
{
pre[++l]=last[x];
last[x]=l;
other[l]=y;
} void dfs(int x,int fa)
{
low[x]=dfn[x]=++time;
int q,p,cnt=;
for (q=last[x];q;q=pre[q])
{
p=other[q];
if (p==fa) continue;
if (!dfn[p])
{
dfs(p,x); cnt++;
getmin(low[x],low[p]);
if (dfn[x]<=low[p]&&fa!=-) cut[x]=;
} else getmin(low[x],dfn[p]);
}
if (fa==-&&cnt>) cut[x]=;
} void make(int x,int fa)
{
int p;
for (int q=last[x];q;q=pre[q])
{
p=other[q];
if (p==fa||cut[p]) continue;
if (!vis[p]) vis[p]=vis[x],make(p,x);
}
} void solve()
{
int m=n; n=;
while (m--)
{
int x,y;
scanf("%d%d",&x,&y);
connect(x,y); connect(y,x);
n=(x>n)?x:n;
n=(y>n)?y:n;
fuck[x]=fuck[y]=;
}
for (int i=;i<=n;i++) if (!dfn[i]) dfs(i,-);
//for (int i=1;i<=n;i++) if (cut[i]) printf("%d ",i);
for (int i=;i<=n;i++) if (!(vis[i]||cut[i])) vis[i]=i,make(i,-);
//for (int i=1;i<=n;i++) printf("%d ",vis[i]); printf("\n");
for (int i=;i<=n;i++) if (vis[i]) size[vis[i]]++;
for (int i=;i<=n;i++)
if (cut[i])
{
memset(flag,,sizeof flag);
for (int q=last[i];q;q=pre[q])
if (!flag[vis[other[q]]]) flag[vis[other[q]]]=,num[vis[other[q]]]++;
}
//for (int i=1;i<=n;i++) printf("%d %d %d\n",i,size[i],num[i]);
for (int i=;i<=n;i++)
if (num[i]==) ans1++,ans2*=size[i];
if (!ans1)
{
ans2=;
for (int i=;i<=n;i++)
if (fuck[i]) ans2++;
}
if (!ans1)
printf("Case %lld: %lld %lld\n",task,2ll,ans2*(ans2-)>>); else
printf("Case %lld: %lld %lld\n",task,ans1,ans2);
} void clear()
{
time=l=ans1=0ll; ans2=1ll;
memset(last,,sizeof last);
memset(dfn,,sizeof dfn);
memset(low,,sizeof low);
memset(cut,,sizeof cut);
memset(vis,,sizeof vis);
memset(size,,sizeof size);
memset(num,,sizeof num);
memset(fuck,,sizeof fuck);
} int main()
{
scanf("%d",&n);
while (n)
{
task++;
clear();
solve();
scanf("%d",&n);
}
return ;
}
bzoj 2730 割点的更多相关文章
- BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)
[HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖 ...
- BZOJ 2730 矿场搭建 Tarjan求割点
思路: Tarjan求出来点双&割点 判一判就行了 //By SiriusRen #include <stack> #include <cstdio> #include ...
- BZOJ 2730: [HNOI2012]矿场搭建( tarjan )
先tarjan求出割点.. 割点把图分成了几个双连通分量..只需dfs找出即可. 然后一个bcc有>2个割点, 那么这个bcc就不用建了, 因为一定可以走到其他救援出口. 只有一个割点的bcc就 ...
- 【刷题】BZOJ 2730 [HNOI2012]矿场搭建
Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...
- bzoj 2730: [HNOI2012]矿场搭建
#include<cstdio> #include<cstring> #include<iostream> #define M 508 using namespac ...
- 【BZOJ 2730】 [HNOI2012]矿场搭建
Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...
- BZOJ 2730 矿场搭建
割点 割点以外的点坍塌不影响其他人逃生,因为假设我们任取两个个非割点s建立救援站,非割点的任意点坍塌,我们都可以从割点走到一个救援出口. 所以我们只考虑割点坍塌的情况. 我们可以先找出图中所有的割点. ...
- [BZOJ 2730][HNOI 2012] 矿场搭建
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2113 Solved: 979[Submit][Statu ...
- bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双
Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...
随机推荐
- 判断滚动条滚动到document底部
滚动条没有实际的高度.只是为了呈现效果才在外型上面有长度. 在js当中也没有提供滚动条的高度API. 参考了网上有关资料:判断滚动条到底部的基本逻辑是滚动条滚动的高度加上视口的高度,正好是docume ...
- 【Linux】- CentOS 防火墙iptables和firewall
1 iptables防火墙 1.1 基本操作 # 查看防火墙状态 service iptables status # 停止防火墙 service iptables stop # 启动防火墙 s ...
- 【TCP】- TCP协议简介
转载:https://blog.csdn.net/ningdaxing1994/article/details/73076795 TCP 是互联网核心协议之一,本文介绍它的基础知识. 一.TCP 协议 ...
- chrome扩展程序中以编程方式插入内容脚本不生效的问题
chrome扩展程序中内容脚本有两种插入方式:(https://crxdoc-zh.appspot.com/extensions/content_scripts) 1. 清单文件: 这种方式会在打开每 ...
- zk分布锁的java实现
只做记录,直接上代码 父类: package com.ylcloud.common.lock; import com.alibaba.fastjson.JSON; import org.I0Itec. ...
- JQuery 学习笔记--02
JS 中的 window.onload() 方法与 Jquery 中的 $(document).read(function( ){ }) 的区别 : 加载时机不一样, window.onload() ...
- BZOJ 1149 风铃(树形DP)
题目描述的实际是一颗二叉树,对于每个结点,要么满叉,要么无叉. 对于一种无解的简单情况,我们搜一遍树找到最浅的叶子结点1和最深的叶子结点2,如果dep[1]<dep[2]-1,则显然无解. 所以 ...
- 【codevs3160】最长公共子串 后缀数组
题目描述 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入 读入两个字符串 输出 输出最长公共子串的长度 样例输入 yeshowmuchiloveyoumydearmotherrea ...
- select模型的原理、优点、缺点
关于I/O多路复用: I/O多路复用(又被称为“事件驱动”),首先要理解的是,操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,它可以给你一 个通知.这样当配合非阻塞的socket ...
- hdu5696区间的价值 -- 2016"百度之星" - 初赛(Astar Round2B)
Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知道,对于长度为k的区 ...