UVALive - 5135 Mining Your Own Business
刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有2个及以上割顶的双连通分量可以不用安放安全井。如果整个图就是一个双连通分量,那么需要安放两个安全井,种类数是n*(n-1)/2.
代码来自刘汝佳白书:
#include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define mp(a, b) make_pair((a), (b))
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define pragma comment(linker, "/STACK:102400000, 102400000")
#define inf 0x0f0f0f0f using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii,int> VII;
typedef vector<int>:: iterator IT;
const int maxn = ;
struct Edge{
int u, v;
Edge(int u, int v):u(u), v(v){}
};
int pre[maxn], low[maxn], bccno[maxn], iscut[maxn], bcc_cnt, dfs_clock;
VI g[maxn], bcc[maxn];
stack<Edge> S;
int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = ;
for(int i = ; i < g[u].size(); i++)
{
int v = g[u][i]; Edge e = Edge(u, v);
if(!pre[v])
{
S.push(e);
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv >= pre[u])
{
iscut[u] = ;
bcc_cnt++; bcc[bcc_cnt].clear();
for(;;)
{
Edge x = S.top(); S.pop();
if(bccno[x.u] != bcc_cnt) {bccno[x.u] = bcc_cnt; bcc[bcc_cnt].pb(x.u);}
if(bccno[x.v] != bcc_cnt) {bccno[x.v] = bcc_cnt; bcc[bcc_cnt].pb(x.v);}
if(x.u == u && x.v == v) break;
}
}
}
else if(pre[v] < pre[u] && v!= fa)
{
S.push(e);
lowu = min(lowu, pre[v]);
}
}
if(child == && fa < ) iscut[u] = ;
return low[u] = lowu;
}
void find_bcc(int n)
{
memset(iscut, , sizeof(iscut));
memset(pre, , sizeof(pre));
memset(bccno, , sizeof(bccno)); dfs_clock = bcc_cnt = ;
for(int i = ; i < n; i++)
if(!pre[i]) dfs(i, -);
}
int kase;
void solve(int n)
{
find_bcc(n);
LL ans1 = , ans2 = ;
for(int i = ; i <= bcc_cnt; i++)
{
int cut_cnt = ;
for(int j = ; j < bcc[i].size(); j++)
if(iscut[bcc[i][j]]) cut_cnt++;
if(cut_cnt == )
ans1++, ans2 *= (LL)(bcc[i].size() - cut_cnt);
}
if(bcc_cnt == )
{
ans1 = , ans2 = (LL)(n-)*n/;
}
printf("Case %d: %I64d %I64d\n", kase, ans1, ans2);
}
int main(void)
{
int m;
while(scanf("%d", &m), m)
{
kase++;
for(int i = ; i < maxn; i++)
g[i].clear();
int mxn = ;
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
mxn = max(mxn, max(u, v));
u--, v--;
g[u].pb(v), g[v].pb(u);
}
solve(mxn);
}
return ;
}
此题的另一种解法是先求出割顶,然后从非割顶的点dfs一遍,注意这个过程中不能经过割顶,统计每次dfs中遇到割顶的数目,如果为1,则更新答案。同样注意割顶为0的情况。
代码:
#include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define mp(a, b) make_pair((a), (b))
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f
#pragma comment(linker, "/STACK:102400000,102400000") using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii,int> VII;
typedef vector<int>:: iterator IT;
const int maxn = + ;
int pre[maxn], low[maxn], iscut[maxn], dfs_clock;
VI g[maxn], cut;
int n;
LL ans1, ans2, cut_cnt;
int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = ;
for(int i = ; i < g[u].size(); i++)
{
int v = g[u][i];
if(!pre[v])
{
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv >= pre[u])
{
iscut[u] = ;
}
}
else if(pre[v] < pre[u] && v != fa)
{
lowu = min(lowu, pre[v]);
}
}
if(child == && fa < )
iscut[u] = ;
return low[u] = lowu;
}
void find_bcc(int n)
{
memset(pre, , sizeof(pre));
memset(iscut, , sizeof(iscut));
dfs_clock = ;
for(int i = ; i < n; i++)
if(!pre[i])
dfs(i, -);
}
int cnt;
void dfs1(int u)
{
cnt++;
pre[u] = ;
for(int i = ; i < g[u].size(); i++)
{
int v = g[u][i];
if(!pre[v])
{
if(iscut[v]) cut_cnt++, cnt++, pre[v] = , cut.pb(v);
else dfs1(v);
}
}
}
void solve(int n)
{
cut.clear();
cut_cnt= ;
memset(pre, , sizeof(pre));
for(int i = ; i < n; i++)
if(iscut[i]) cut_cnt++; if(cut_cnt == ) ans1 = , ans2 = (LL)n*(n-)/;
else for(int i = ; i < n; i++)
if(!pre[i] && !iscut[i])
{
cut_cnt = cnt = ;
dfs1(i);
for(int i = ; i < cut.size(); i++)
pre[cut[i]] = ;
cut.clear();
if(cut_cnt == )
ans1++, ans2 *= (LL)(cnt-);
}
}
int main(void)
{
int m, t = ;
while(scanf("%d", &m), m)
{
n = ;
ans1 = , ans2 = ;
for(int i = ; i < maxn; i++)
g[i].clear();
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
n = max(n, max(u, v));
u--, v--;
g[u].pb(v);
g[v].pb(u);
}
find_bcc(n);
solve(n);
printf("Case %d: %I64d %I64d\n", t, ans1, ans2);
t++;
}
return ;
}
UVALive - 5135 Mining Your Own Business的更多相关文章
- UVALive - 5135 - Mining Your Own Business(双连通分量+思维)
Problem UVALive - 5135 - Mining Your Own Business Time Limit: 5000 mSec Problem Description John D ...
- UVALive 5135 Mining Your Own Business 双连通分量 2011final
题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱, ...
- UVALive 5135 Mining Your Own Business 双连通分量
据说这是一道Word Final的题,Orz... 原题链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&a ...
- LA 5135 Mining Your Own Business
求出 bcc 后再……根据大白书上的思路即可. 然后我用的是自定义的 stack 类模板: #include<cstdio> #include<cstring> #includ ...
- UVALive 5135 Mining Your Own Bussiness【tarjan点双】
LINK1 LINK2 题目大意 给你一个无向连通图,让你给一些点染上黑色,需要满足染色之后,断开任意一个节点,要满足任意一个联通块中剩下的节点中至少有一个黑点 思路 一开始想的是把每一个点双联通分量 ...
- 【LA】5135 Mining Your Own Business
[算法]点双连通分量 [题解]详见<算法竞赛入门竞赛入门经典训练指南>P318-319 细节在代码中用important标注. #include<cstdio> #includ ...
- 训练指南 UVALive - 5135 (双连通分量)
layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...
- HDU3844 Mining Your Own Business
HDU3844 Mining Your Own Business 问题描述John Digger是一个大型illudium phosdex矿的所有者.该矿山由一系列隧道组成,这些隧道在各个大型交叉口相 ...
- 「题解报告」SP16185 Mining your own business
题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
随机推荐
- 【转】MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
[转]MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作 上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据, ...
- 【C#4.0图解教程】笔记(第1章~第8章)
第1章 C#和.NET框架 1..NET框架的组成 .NET框架由三部分组成(严格来说只有CLR和FCL(框架类库)两部分),如图 执行环境称为:CLR(公共语言运行库),它在运行期管理程序的执行. ...
- python 安装第三方库,超时报错--Read timed out.
Traceback (most recent call last): File "/home/xiaoduc/.pyenv/versions/3.5.0/lib/python3.5/site ...
- 编译gd-2.0.35.tar.gz时报错:gd_png.c:16:53: error: png.h: No such file or directory
编译gd-2.0.35.tar.gz时报错: gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/local/freetype/include/freetype2 -I/us ...
- java_集合框架
一.集合框架图 二.Collection接口 Collection中可以存储的元素间无序,可以重复的元素. Collection接口的子接口List和Set,Map不是Collecti ...
- Java语言----三种循环语句的区别
------- android培训.java培训.期待与您交流! ---------- 第一种:for循环 循环结构for语句的格式: for(初始化表达式;条件表达式;循环后的操作表达式 ...
- attempt to write a readonly database 的解决办法
这个问题导致我的unity项目崩溃,以至于无法打开. 第一次出现这个问题是因为在Lighting窗口中build按钮下点击了clear all baked datas,导致unity强制退出,并给出上 ...
- [翻译][MVC 5 + EF 6] 9:异步和存储过程
原文:Async and Stored Procedures with the Entity Framework in an ASP.NET MVC Application 1.为什么使用异步代码: ...
- Windows server2008/2012 安装oracle 11 创建实例HANG住在百分之2
Windows server2008/2012 安装oracle 11.2.0.1的时候,可能会在创建数据库实例的时候卡在百分之2的地方. 这个时候可以 1.点击开始菜单,在“搜索程序和文件”中输入“ ...
- javascript控制子页面对父页面控件操作
//赋值 window.parent.document.getElementById("partyid_trade_edit").value = data.data.partyid ...