首先我们知道,对于这张图,我们可以枚举坍塌的是哪个点,对于每个坍塌的点,最多可以将图分成若干个不连通的块,这样每个块我们可能需要一个出口才能满足题目的要求,枚举每个坍塌的点显然是没有意义的,我们只需要每个图的若干个割点,这样除去割点的图有若干个块,我们可以求出只与一个割点相连的块,这些块必须要一个出口才能满足题目的要求,每个块内有块内个数种选法,然后将所有满足一个割点相连的块的点数连乘就行了。

  对于每个与一个割点相连的块必须建出口可以换一种方式理解,我们将每个块看做一个点,那么算上割点之后,这张图就变成了一颗树,只有叶子节点我们需要建立出口,因为对于非叶子节点我们不论断掉哪个点我们都有另一种方式相连,这里的叶子节点就是与一个割点相连的块。

  最后还有个特判,就是对于一个双连通图,我们至少需要选取两个点作为出口,因为如果就选一个,可能该点为坍塌点,这时我们就任选两个点就行了,方案数为点数*(点数-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 割点的更多相关文章

  1. BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)

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

  2. BZOJ 2730 矿场搭建 Tarjan求割点

    思路: Tarjan求出来点双&割点 判一判就行了 //By SiriusRen #include <stack> #include <cstdio> #include ...

  3. BZOJ 2730: [HNOI2012]矿场搭建( tarjan )

    先tarjan求出割点.. 割点把图分成了几个双连通分量..只需dfs找出即可. 然后一个bcc有>2个割点, 那么这个bcc就不用建了, 因为一定可以走到其他救援出口. 只有一个割点的bcc就 ...

  4. 【刷题】BZOJ 2730 [HNOI2012]矿场搭建

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

  5. bzoj 2730: [HNOI2012]矿场搭建

    #include<cstdio> #include<cstring> #include<iostream> #define M 508 using namespac ...

  6. 【BZOJ 2730】 [HNOI2012]矿场搭建

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

  7. BZOJ 2730 矿场搭建

    割点 割点以外的点坍塌不影响其他人逃生,因为假设我们任取两个个非割点s建立救援站,非割点的任意点坍塌,我们都可以从割点走到一个救援出口. 所以我们只考虑割点坍塌的情况. 我们可以先找出图中所有的割点. ...

  8. [BZOJ 2730][HNOI 2012] 矿场搭建

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

  9. bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双

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

随机推荐

  1. 2-c语言作业1

    #include<stdio.h> #include<math.h> int main(void) { int money,year; double rate,sun; pri ...

  2. C# 压缩组件介绍与入门

    1.前言 作为吉日嘎拉权限管理系统最早的一批学习版用户,学了不少东西,在群里面也结识了很多朋友,更重要的是闲余时间,大家都发布很多可靠的外包工作.这次也是由于吉日嘎拉发布了一个有关“压缩文件损坏检测” ...

  3. Matlab画平滑曲线的两种方法

    自然状态下,用plot画的是折线,而不是平滑曲线. 有两种方法可以画平滑曲线,第一种是拟合的方法,第二种是用spcrv,其实原理应该都一样就是插值.下面是源程序,大家可以根据需要自行选择,更改拟合的参 ...

  4. [OS] 多线程--原子操作 Interlocked系列函数

    转自:http://blog.csdn.net/morewindows/article/details/7429155 上一篇<多线程--第一次亲密接触 CreateThread与_begint ...

  5. 去除安卓手机select下拉框默认箭头

    -webkit-appearance: listbox;

  6. CSS-posiziton

    1. 想要实现,”返回顶部”永远位于页面的右下角.需要用到position函数.CSS:层叠样式表.用到了分层的功能. position:fixed;  永远固定在一个地方. <!DOCTYPE ...

  7. 【题解】洛谷P3709大爷的字符串题

    最近想要练习一下莫队(实在是掌握的太不熟练了啊.)这题一开始看到有点懵(题面杀),后来发现是要求众数的个数.乍一看好像很难的样子. 但仔细分析一下:首先往序列当中加入一个数,这个是很简单的,只需要维护 ...

  8. 【刷题】BZOJ 4830 [Hnoi2017]抛硬币

    Description 小A和小B是一对好朋友,他们经常一起愉快的玩耍.最近小B沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到SSR,让他非常怀疑人生.勤勉的小A为 ...

  9. [洛谷P4345][SHOI2015]超能粒子炮·改

    题目大意:给你$n,k$,求:$$\sum\limits_{i=0}^k\binom n i\pmod{2333}$$题解:令$p=2333,f(n,k)\equiv\sum\limits_{i=0} ...

  10. bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...