题意:

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

思路:

  要使得任意撤掉一个点都能使其他点能够到达黑点,那么点双连通分量能保证这点,那么就在同个点双连通分量内涂黑1个点。但是每个【点双连通分量】都涂吗?太浪费颜料了,那就缩点成树,只需要涂叶子即可,那就找度为1的缩点。但是种数呢?叶子内的点除了割点外都是可以涂黑的,因为如果黑色割点被撤掉,那么叶子中的其他点怎么办?所以不能涂割点,每个黑点有【叶子中的点数-1】种涂法,所有黑店的涂法相乘为第2个结果。

  特殊情况,因为给的是连通图且至少有2个点,那么还可能会出现没有割点的情况(仅1个点双连通分量),那就直接涂黑两个,以防一个黑点被撤掉。

  此题出现的连续的点可能多达10万个,DFS就会爆栈。在C++下可以手动开栈,G++下的还不清楚怎么开。

 #pragma comment(linker,"/STACK:102400000,102400000")//开栈
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <stack>
#define LL long long
#define pii pair<int,int>
using namespace std;
const int N=+;
const int INF=0x7f7f7f7f;
int up;
int low[N], dfn[N];
bool iscut[N];
int dfn_clock, bcc_cnt, bcc_no[N];
unordered_map<int,int> mapp;
stack< pii > stac;
vector<int> bcc[N], vect[N]; void DFS(int x, int far)//tarjan
{
dfn[x]=low[x]=++dfn_clock; int chd=;
for(int i=; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(!dfn[t])
{
chd++;
stac.push(make_pair(x,t));
DFS(t,x);
low[x]=min( low[x], low[t]);
if(low[t]>=dfn[x])
{
iscut[x]=true; //需要标记割点
bcc[++bcc_cnt].clear();
while(true)
{
int a=stac.top().first;
int b=stac.top().second;
stac.pop();
if(bcc_no[a]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(a);
bcc_no[a]=bcc_cnt;
}
if(bcc_no[b]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(b);
bcc_no[b]=bcc_cnt;
}
if(a==x&&b==t) break;
}
}
}
else if( dfn[t]<dfn[x] && t!=far)
{
stac.push(make_pair(x,t));
low[x]=min(low[x],dfn[t]);
}
}
if(chd==&&far==) iscut[x]=false; //根
} void find_bcc(int Case)
{
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(iscut,,sizeof(iscut));
memset(bcc_no,,sizeof(bcc_no)); dfn_clock=bcc_cnt=;
for(int i=; i<=up; i++) if(!dfn[i]) DFS(i,); //深搜
LL ans1=,ans2=; for(int i=; i<=bcc_cnt; i++) //统计度为多少
{
int cnt=;
for(int j=; j<bcc[i].size(); j++) if(iscut[bcc[i][j] ]) cnt++; //有割点就统计连通分量i的度。
if(cnt==) ans1++, ans2*=bcc[i].size()-;
}
if(bcc_cnt==) ans1=,ans2=(LL)bcc[].size()*(bcc[].size()-)/;
printf("Case %d: %lld %lld\n", Case, ans1, ans2);
} int main()
{
freopen("input.txt", "r", stdin);
int a, b, n, j=;
while(scanf("%d",&n), n)
{
mapp.clear();
for(int i=; i<N; i++) vect[i].clear();
up=;
for(int i=; i<n; i++)
{
scanf("%d%d",&a,&b);
if(!mapp[a]) mapp[a]=++up;
if(!mapp[b]) mapp[b]=++up;//点号缩小为连续 vect[mapp[a]].push_back(mapp[b]);
vect[mapp[b]].push_back(mapp[a]);
}
find_bcc(++j);
}
return ;
}

AC代码

HDU 3844 Mining Your Own Business(割点,经典)的更多相关文章

  1. HDU 3844 Mining Your Own Business

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

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

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

  3. HDU3844 Mining Your Own Business

    HDU3844 Mining Your Own Business 问题描述John Digger是一个大型illudium phosdex矿的所有者.该矿山由一系列隧道组成,这些隧道在各个大型交叉口相 ...

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

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

  5. HDU 2181 哈密顿绕行世界问题(经典DFS+回溯)

    哈密顿绕行世界问题 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  6. HDU 3038 - How Many Answers Are Wrong - [经典带权并查集]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...

  7. HDU 1789 Doing Homework again(非常经典的贪心)

    Doing Homework again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  8. HDU 1180 诡异的楼梯(超级经典的bfs之一,需多回顾)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1180 诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others)     ...

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

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

随机推荐

  1. Matlab中@与函数调用

    function m f=@(x) x^2; y(f,3); function y(f,x) disp(num2str(f(x))); end end 函数调用另一个函数的时候,把另一个函数名作为参数 ...

  2. ios开发之多线程资源争夺

    上一篇介绍了常用的多线程技术,目前开发中比较常用的是GCD,其它的熟悉即可.多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用率来提高系统的整体性能,但是会出现多个线程对同一资源 ...

  3. 解决myeclipse每次启动注册码过期输入注册码

    每次都需要重新输入一个新的注册码,搞的很不愉快,后来发现原来是因为在[我的文档]下面有一个myeclipse的配置文件,叫.myeclipse.properties 你可以全盘搜索一下这个文件,然后改 ...

  4. model对象之setter方法使用,解决去除空格和将数字转成字符串展示方法

    1.系统中手机号注册的时候,不能含有前后空格.在model对象中过滤~! private String mobile; public String getMobile() { return mobil ...

  5. Java垃圾收集器

    概述 说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用 ...

  6. hdu 1863 畅通工程(最小生成树,基础)

    题目 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include<string.h> #include <ma ...

  7. C# Log4Net配置

    Log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等),日志就是程序的黑匣子,可以通过日志查看系统的运行过程,从而发现系统的问题.日志的作用:将运 ...

  8. 2013 ACM-ICPC长沙赛区全国邀请赛——Bottles Arrangement

    这题当时竟然没看啊…… 找规律:求和m+m+m-1+m-1+……前n项 ;}

  9. Android 虚拟机安装SD卡

    在cmd命令行下,进入platform-tools目录下.   1.创建sdcard   mksdcard -l mycard 256M E:\android\myCards\mysdcard.img ...

  10. Android 通过程序添加桌面快捷方式

    原理:通过代码向 Launcher 中的广播接收者发送广播来创建快捷图标. 首先要声明的权限是: <!--添加图标的权限--> <uses-permission android:na ...