HDU3844 Mining Your Own Business

问题描述
John Digger是一个大型illudium phosdex矿的所有者。该矿山由一系列隧道组成,这些隧道在各个大型交叉口相遇。与一些业主不同,Digger实际上关心他的工人的福利,并担心矿山的布局。具体来说,他担心可能会出现一个交汇处,如果发生倒塌,会将矿井的一个区域的工人与其他工人隔离开来(如你所知,illudium phosdex非常不稳定)。为了解决这个问题,他希望从交叉点到地面安装特殊的逃生轴。他可以在每个交叉点安装一个逃生轴,但Digger并不关心他的工人那么多。相反,他想安装最少数量的逃生轴,这样如果任何一个交叉点坍塌,所有在交叉点坍塌中幸存的工人将拥有通往地面的路径。
编写一个程序来计算最小的逃生轴数量以及可以安装这个最小数量的逃生轴的总方式。
输入
输入包含几个测试用例。每种情况的第一行包含正整数N(N <= 5×10 ^ 4),表示矿井隧道的数量。在此之后是N行,每行包含两个不同的整数s和t,其中s和t是结号。连接点从1开始连续编号。每对连接点最多由一个隧道连接。每组矿井隧道形成一个连接单元(也就是说,您可以从任何一个交叉点到达任何其他交叉点)。
最后一个测试用例后面是一个包含单个零的行。
输出
对于每个测试案例,显示其案例编号,然后显示矿井隧道系统所需的最小数量的逃生轴以及这些逃生轴的安装方案数。您可以假设结果适合带符号的64位整数。

题意:给定一个无向连通图,选择一些特殊点,当图中任意一个点(也有可能是特殊点)被删去的时候,其他点至少能到达一个特殊点。

显然我们不会将割点作为特殊点,因为如果割点被去掉,他所在的dcc仍然要有特殊点,而此时割点是没有必要做特殊点的,对于包含两个及以上割点的dcc也是不需要特殊点的,即使一个割点被去掉,这个dcc仍然可以通过其他割点到其他dcc,因此特殊点一定在割点数量为1的dcc内,方案数就很显然了,乘起来就可以了。另外如果整张图是一个dcc,之前的分析就没有用了,此时显然需要2个特殊点,方案数为C(n,2)。另外这个题没有给点的个数,但保证是连续的(不然又要离散化了……),所以可以在输入的时候取max来求得。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define int long long
#define MAXN 100010
#define LL long long
#define ma(x) memset(x,0,sizeof(x))
using namespace std;
struct edge
{
int u,v,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define n(x) ed[x].nxt
#define u2(x) ed2[x].u
#define v2(x) ed2[x].v
#define n2(x) ed2[x].nxt
}ed[MAXN*10],ed2[MAXN*10];
int first[MAXN],num_e;
#define f(x) first[x]
int first2[MAXN],num_e2;
#define f2(x) first2[x] int n,m;
int dfn[MAXN],low[MAXN],num,root;
int stack[MAXN],top,cnt;
bool cut[MAXN];
vector<int> dcc[MAXN];
int c[MAXN],du[MAXN];
void tarjan(int x)
{
dfn[x]=low[x]=++num;
stack[++top]=x;
if(x==root&&!f(x)){dcc[++cnt].push_back(x);return;}
int flag=0;
for(int i=f(x);i;i=n(i))
if(!dfn[v(i)])
{
tarjan(v(i)),low[x]=min(low[v(i)],low[x]);
if(low[v(i)]>=dfn[x])
{
flag++;
if(x!=root||flag>1)cut[x]=1;
cnt++;int z;
do{dcc[cnt].push_back(z=stack[top--]);}while(z!=v(i));
dcc[cnt].push_back(x);
}
}
else low[x]=min(low[x],dfn[v(i)]);
}
void init()
{
ma(first);ma(first2);ma(dfn);ma(low);ma(cut);ma(c);ma(du);ma(dcc);
num_e=num_e2=n=num=top=cnt=0;
}
inline void add(int u,int v);
inline void add2(int u,int v);
signed main()
{
// freopen("in.txt","r",stdin); for(int ooo=1;;ooo++)
{
scanf("%lld",&m);if(!m)break;
init();
printf("Case %lld: ",ooo);
int a,b;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld",&a,&b);
n=max(max(a,b),n);
add(a,b),add(b,a);
}
for(int i=1;i<=n;i++)
if(!dfn[i]){root=i;tarjan(i);}
if(cnt==1){printf("2 %lld\n",n*(n-1)/2);continue;}
num=cnt;
for(int i=1;i<=n;i++)
if(cut[i])c[i]=++num;
for(int i=1;i<=cnt;i++)
for(int j=0;j<dcc[i].size();j++)
{
int x=dcc[i][j];
if(cut[x])add2(i,c[x]),add(c[x],i),du[i]++;
else c[x]=i;
}
int ans=0,fa=1;
for(int i=1;i<=cnt;i++)
if(du[i]==1)
{
ans++;
fa*=dcc[i].size()-1;
}
printf("%lld %lld\n",ans,fa);
}
}
inline void add(int u,int v)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
n(num_e)=f(u);
f(u)=num_e;
}
inline void add2(int u,int v)
{
++num_e2;
u2(num_e2)=u;
v2(num_e2)=v;
n2(num_e2)=f2(u);
f2(u)=num_e2;
}

HDU3844 Mining Your Own Business的更多相关文章

  1. hdu3844 Mining Your Own Business,无向双连接组件

    点击打开链接 无向图的双连通分量 #include<cstdio> #include<stack> #include<vector> #include<map ...

  2. UVALive - 5135 - Mining Your Own Business(双连通分量+思维)

    Problem   UVALive - 5135 - Mining Your Own Business Time Limit: 5000 mSec Problem Description John D ...

  3. 「题解报告」SP16185 Mining your own business

    题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...

  4. UVA5135 Mining Your Own Business ( 无向图双连通分量)

    题目链接 题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太 ...

  5. HDU 3844 Mining Your Own Business

    首先,如果图本来就是一个点双联通的(即不存在割点),那么从这个图中选出任意两个点就OK了. 如果这个图存在割点,那么我们把割点拿掉后图就会变得支离破碎了.对于那种只和一个割点相连的块,这个块中至少要选 ...

  6. LA 5135 Mining Your Own Business

    求出 bcc 后再……根据大白书上的思路即可. 然后我用的是自定义的 stack 类模板: #include<cstdio> #include<cstring> #includ ...

  7. UVA 1108 - Mining Your Own Business

    刘汝佳书上都给出了完整的代码 在这里理一下思路: 由题意知肯定存在一个或者多个双连通分量: 假设某一个双连通分量有割顶.那太平井一定不能打在割顶上. 而是选择割顶之外的随意一个点: 假设没有割顶,则要 ...

  8. HDU 3844 Mining Your Own Business(割点,经典)

    题意: 给出一个连通图,要求将某些点涂黑,使得无论哪个点(包括相关的边)撤掉后能够成功使得剩下的所有点能够到达任意一个涂黑的点,颜料不多,涂黑的点越少越好,并输出要涂几个点和有多少种涂法. 思路: 要 ...

  9. UVALive - 5135 Mining Your Own Business

    刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有2个及以上割顶的双连通分量可以不 ...

随机推荐

  1. oracle建立job定期运行存储过程

    1 首先查看 SQL> show parameter job NAME TYPE VALUE------------------------------------ ----------- -- ...

  2. HDU5583 Kingdom of Black and White

    Kingdom of Black and White Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

  3. 【react】react-reading-track

    这是一个很有趣的图书阅读demo 先放github地址:https://github.com/onlyhom/react-reading-track 我觉得这个博主的项目很有意思呢 我们一起看看代码啊 ...

  4. Vue Router 相关

    1. 路由传参: 编程式的导航 router.push this.$router.push("home"); this.$router.push({ name: 'news', p ...

  5. pyenv虚拟环境管理python多版本和软件库

    可能大家在日常工作中会遇到这么个问题,现在基本的linux系统都是自带老版本的python2.7.x版本,我又不想用老版本,但直接升级可能会出问题,或是依赖老版本的程序就运行不了,有没办法能安装3.x ...

  6. Struts framework

    Struts功能详解——ActionMapping对象 Struts旅程(一)Struts简介和原理 实例讲解DispatchAction和LookupDispatchAction DispatchA ...

  7. 【JZOJ3617】【ZJOI2014】力

    ╰( ̄▽ ̄)╭ 对于100%的数据,n≤100000;0<qi<1,000,000,000. (⊙ ▽ ⊙) 令ri=1i2, 设Fj=∑j−1i=0qi∗rj−1−i,Gj=∑j−1i= ...

  8. C++之自定义key类型,重载操作符

    #include <map>#include <string>using namespace std;class MyString{ public:MyString(){m_s ...

  9. 配置了两天python【python可以的】

    首先是看cs231n 发现代码的版本是py2 而我只装了 py3(anaconda3) 怎么办呢 于是想办法装了 anaconda2 并与之共存 ,调用的时候用 activate py2调用 http ...

  10. 【水滴石穿】rn_statusbar

    先放项目地址https://github.com/hezhii/rn_statusbar 来看一下效果 咩有感觉很怎么样,看代码 根入口文件 //index.js //看代码我们知道入口是app.js ...