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

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

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

    https://vjudge.net/contest/67836#problem/K n people numbered 1 to n around a circle, we eliminate ev ...

  2. js图片转换为base64

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Dubbo分享

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  4. C# 反射与dynamic最佳组合

    在 C# 中反射技术应用广泛,至于什么是反射.........你如果不了解的话,请看下段说明,否则请跳过下段.广告一下:喜欢我文章的朋友请关注一下我的blog,这也有助于提高本人写作的动力. 反射:当 ...

  5. 每个zone的low memory是怎么计算出来的

    内核都是试图让活动页和不活动页的数量均衡 在分配内存时每次都会唤醒wakeup_swapd,这个函数会在 现在是不是已经没有全局的LRU表了?已经都变成per cgroup级别的LRU表了吗? ina ...

  6. 【Linux】linux中删除指定文件外所有其他文件(夹)的问题

    今天碰到要删除指定文件(夹)外的其他文件的问题.网上查到的方法是这样的 需要在当前文件夹中进行: rm -rf !(keep) #删除keep文件之外的所有文件 rm -rf !(keep1|keep ...

  7. Java InputStream转File

    文件处于磁盘上或者流处于内存中 在输入流有已知的和预处理的数据时,如在硬盘上的文件或者在流处于内存中.这种情况下,不需要做边界校验,并且内存容量条件允许的话,可以简单的读取并一次写入. InputSt ...

  8. bzoj1069-最大土地面积

    题目 给定\(n\ (n\le 2000)\)个坐标,求四个坐标使得围起来的四边形面积最大. 分析 最暴力的想法是枚举四个点,然而肯定超时.接着不知道怎么想到中途相遇,然而一点关系都没有.这里用到了一 ...

  9. YY的GCD 莫比乌斯反演

    ---题面--- 题解: $ans = \sum_{x = 1}^{n}\sum_{y = 1}^{m}\sum_{i = 1}^{k}[gcd(x, y) == p_{i}]$其中k为质数个数 $$ ...

  10. BZOJ2816:[ZJOI2012]网络——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2816 https://www.luogu.org/problemnew/show/P2173 有一 ...