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 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
随机推荐
- 第一个Cookie应用
Cookie应用:显示用户上次访问时间 package com.itheima.cookie; import java.io.IOException; import java.io.PrintWrit ...
- akka创建actor时报错:IllegalArgumentException: no matching constructor found on class $iwC$$iwC$$iwC$$iwC$
在spark-shell中输入范例中的代码: import akka.actor.Actor import akka.actor.Props import akka.event.Logging cla ...
- ###《Machine Learning》by Andrew NG
点击查看Evernote原文. #@author: gr #@date: 2014-10-17 #@email: forgerui@gmail.com Fundamental 一. 矩阵的迹.秩 矩阵 ...
- Objective-C 【多态】
------------------------------------------- 多态的概念.实现以及注意事项 程序中的多态:不同的对象 以自己的方式去 响应 相同方法名(父类同 ...
- C# 高精度减法 支持小数(待优化)
是现实思路 1,先小数点补位,8913758923475893274958738945793845-4893127498372459823745324532453245.284929384729837 ...
- 只有PD号的调起
cicsterm-> CECI -> LI-> P -> TestQuery
- n个骰子的点数
把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s.输入n,打印出s的所有可能的值和出现的概率. 解法一:基于递归求骰子点数. /////////////////基于递归求骰子点数///////// ...
- 九度OJ 1511 从尾到头打印链表
题目地址:http://ac.jobdu.com/problem.php?pid=1511 题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例. 每一组测 ...
- Linux下的I/O复用与epoll详解
前言 I/O多路复用有很多种实现.在linux上,2.4内核前主要是select和poll,自Linux 2.6内核正式引入epoll以来,epoll已经成为了目前实现高性能网络服务器的必备技术.尽管 ...
- CentOS 根据命令查所在的包
在工作中经常会遇到想用某个命令机器没装却又不知道命令在哪个包(源码编译不再本文范围内),下面介绍个比较笨的方法可以帮助我们搞定这个问题. 说明:蓝色=命令名称 浅绿=命令参数 ...