题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27016

题意:求一个连通图去掉任意一个点以及与它相连的边,图中的所有蚂蚁可以通过某些点中建造的矿井逃到地面,求最少要在图中的几个点中建造矿建,这样建造矿井的方案的总数。

思路:首先求点双连通分量,标记割点,然后我们可以分析,若一个连通分量中有且仅有一个割点,那么除了这个割点之外,别的点都能造矿井,且只需在除了这个割点之外的某个点上造一座矿井就可以了(假设破话的是这个割点,那么这个连通分量中的蚂蚁可以通过有矿井的点逃到表面,但是如果矿井恰好造在割点上,那么一旦去掉了割点之后,蚂蚁就无法逃到地面上去了(这就是为什么不选割点的原因)。至于为什么别的点可以呢,假设破话的点恰好就是有矿井的这个点,那么这个连通分量中的蚂蚁可以通过割点跑到别的点双连通分量中逃生)。然后我们就只需要找有且只有一个割点的点双连通分量有多少个就行了,然后在每个连通分量中选择任何一个不是割点的点建造矿井就行了,至于有多少种方案,也就好求了,直接连通分量的点的个数(除去割点)相乘即可。然后我想说一下为什么对于那些点连通分量中割点大于等于2的就不用选呢,其实我们画一下图就知道了,因为破话这个连通分量的任何一个点以及与它相连的边,这个连通分量的中蚂蚁还是可以通过其中一个割点跑到另一个连通分量中去逃生。这样我们就得到了割点数目等于1和大于等于2的情况,那么对于图中没有割点的情况我们应该怎么选,这也好办,画个图就明白了,只需任选两个点建造矿井就可以了,当破话了某个有矿井的点之后,蚂蚁可以通过另一个有矿井的点逃生,那么总的方案数为n*(n-1)/2。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
#define MAXN 22222
typedef long long ll;
typedef unsigned long long llu; struct Edge{
int v,next;
}edge[MAXN<<]; int n,m,NE;
int head[MAXN]; void Insert(int u,int v)
{
edge[NE].v=v;
edge[NE].next=head[u];
head[u]=NE++;
} int cnt,bcc_count,cut_count;
int low[MAXN],dfn[MAXN];
vector<vector<int> >blocks;
bool mark[MAXN];
bool is_cutpoint[MAXN];
stack<int>S; void Tarjan(int root,int u,int father)
{
int rt_son=;
low[u]=dfn[u]=++cnt;
mark[u]=true;
S.push(u);
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(v==father)continue;
if(dfn[v]==){
Tarjan(root,v,u);
low[u]=min(low[u],low[v]);
if(u==root)rt_son++;
if(low[v]>=dfn[u]){
int x;
do{
x=S.top();
S.pop();
mark[x]=false;
blocks[bcc_count].push_back(x);
}while(v!=x);
blocks[bcc_count].push_back(u);
bcc_count++;
if(u!=root)is_cutpoint[u]=true;
}
}else if(mark[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(u==root&&rt_son>=)is_cutpoint[u]=true;
} int main()
{
int _case,u,v,t=;
scanf("%d",&_case);
while(_case--){
scanf("%d%d",&n,&m);
NE=;
memset(head,-,sizeof(head));
blocks.clear();
blocks.resize(n+);
while(!S.empty())S.pop();
while(m--){
scanf("%d%d",&u,&v);
Insert(u,v);
Insert(v,u);
}
cnt=bcc_count=;
memset(mark,false,sizeof(mark));
memset(is_cutpoint,false,sizeof(is_cutpoint));
memset(dfn,,sizeof(dfn));
Tarjan(,,-);
ll ans=;
llu ways=;
int cut_count=;
for(int i=;i<n;i++)if(is_cutpoint[i])cut_count++;
if(cut_count==){
printf("Case %d: %d %d\n",t++,,n*(n-)/);
continue;
}
for(int i=;i<bcc_count;i++){
cnt=;
for(int j=;j<blocks[i].size();j++){
int v=blocks[i][j];
if(is_cutpoint[v])cnt++;
}
if(cnt<){
ans++;
ways*=(llu)(blocks[i].size()-);
}
}
printf("Case %d: %lld %llu\n",t++,ans,ways);
}
return ; }

loj 1308(点双连通分量应用)的更多相关文章

  1. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  2. 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分

    E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...

  3. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

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

  4. hihoCoder 1184 连通性二·边的双连通分量

    #1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老 ...

  5. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  6. 点/边 双连通分量---Tarjan算法

    运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...

  7. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  8. poj3177 && poj3352 边双连通分量缩点

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12676   Accepted: 5368 ...

  9. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

随机推荐

  1. linux c程序中获取shell脚本输出的实现方法

    linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作. ...

  2. 大数据下Limit使用(MySQL)

    对于一直用Oracle的我,今天可是非常诧异,MySQL中同一个函数在不同数量级上的性能居然差距如此之大. 先看表ibmng(id,title,info)  唯一  id key 索引title 先看 ...

  3. FrameSize、WinSize、VisibleSize、VisibleOrigin区别

    FrameSize 手机屏幕分辨率,通过CCEGLView::sharedOpenGLView()->getFrameSize()获得,不同的分辨率手机这个值不同 WinSize 设计分辨率,固 ...

  4. Ninth scrum meeting - 2015/11/3

    今天课上老师询问了每个团队的进度,我们发现有好多团队都已经基本完成了, 距离预定的alpha版本开发完成时间也越来越近了,我们的工作也都在有条不紊的进行着.今天又出现了git pull时有冲突的情况, ...

  5. characterCustomezition的资源打包代码分析

    using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; class Creat ...

  6. UIImagePickerController详解

    转载自:http://blog.csdn.net/kingsley_cxz/article/details/9157093 1.UIImagePickerController的静态方法: imagep ...

  7. python学习之最简单的用户注册及登录验证小程序

    文章都是从我的个人博客上粘贴过来的哦,更多内容请点击 http://www.iwangzheng.com 正如很多同学所知道的,楼主开始学习python了,前进的道路曲曲折折,有荆棘也有陷阱,从最简单 ...

  8. poj2996 模拟

    Help Me with the Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3713   Accepted:  ...

  9. 【Network】一张图看懂 Reactor 与 Proactor 模型的区别

    首先来看看Reactor模式,Reactor模式应用于同步I/O的场景.我们以读操作为例来看看Reactor中的具体步骤:读取操作:1. 应用程序注册读就需事件和相关联的事件处理器2. 事件分离器等待 ...

  10. (转)Sublime Text 2 2.0.2 序列号

    ----- BEGIN LICENSE -----Andrew WeberSingle User LicenseEA7E-855605813A03DD 5E4AD9E6 6C0EEB94 BC9979 ...