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

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

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

    方法1:所有权法 父窗体:Form1    子窗体:Form2 //Form1:窗体代码 //需要有一个公共的刷新方法 public void Refresh_Method() { //... } / ...

  2. Thinkphp5获取数据库数据到视图

    这是学习thinkhp5的基础篇笔记. 本文主要讲怎么配置数据库链接,以及查询数据库数据,并且最后将数据赋给视图. 数据库配置: thinkphp5的数据库配置默认在conf下的database.ph ...

  3. JXM 监控tomcat 7(含代码

    1.在tomcat的server.xml中加入: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleL ...

  4. 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀请小熊维尼前来 ...

  5. 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  6. 【题解】HNOI2016序列

    也想了有半天,没有做出来……实际上做法确实也是十分精妙的.这里推荐一个blog,个人认为这位博主讲得挺好了:Sengxian's Blog; 感觉启示是:首先要加强对莫队算法 & ST表的熟练 ...

  7. AOJ.720 丢失的学妹

    缺失的学妹 考察点 STL MAP Time Mem Len Lang 3.81s 39.1MB 0.68K G++ 题意分析 给出妹子学号的个数n,给出n个学号,和n-1个学号,求在n学号中那个没有 ...

  8. sourcemap总结

    sourcemap在线上压缩文件调试中很重要,在此总结如下: 1. 开启sourcemap (1). 浏览器要开启source-map支持(2). 压缩文件底部要有source-map的URL,压缩要 ...

  9. SRM12 T2夏令营(分治优化DP+主席树 (已更新NKlogN)/ 线段树优化DP)

     先写出朴素的DP方程f[i][j]=f[k][j-1]+h[k+1][i] {k<i}(h表示[k+1,j]有几个不同的数)  显然时间空间复杂度都无法承受   仔细想想可以发现对于一个点 i ...

  10. YBT 5.1 区间类动态规划

    题解在代码中 石子合并[loj 10147] /* dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) i<=k& ...