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 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
随机推荐
- html同一个页面多个倒计时
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...
- 预算oracle
select * from ( )) CODE_VERSION from ( SELECT tb_cube_fc05.pk_entity pk_org,/*主体pk*/ org_orgs.code o ...
- casperjs 抓取爱奇艺高清视频
CasperJS 是一个开源的导航脚本和测试工具,使用 JavaScript 基于 PhantomJS 编写,用于测试 Web 应用功能,Phantom JS是一个服务器端的 JavaScript A ...
- 编译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 ...
- PL/SQL Developer 使用中文条件查询时无数据的解决方法
PL/SQL Developer 使用中文条件查询时无数据,这是由于字符集的不一致导致的. 执行以下sql命令:select userenv('language') from dual; 显示:SIM ...
- Codevs 1069 关押罪犯 2010年NOIP全国联赛提高组
1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description S 城现有两座监狱,一共 ...
- [openMP] OpenMP在visual studio和mac上的配置
今天弄了半天才弄好mac上的openmp,一方面智商下限,另一方面竟然发现网上也没有什么详细过程,特意把我的配置过程贴上来 多核编程可以认为是对多线程编程做了一定程度的抽象,提供一些简单的API,使得 ...
- Java如何获得平台相关的行分隔符、路径分隔符?
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3550194.html ,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体 ...
- OCI_ERROE - errcode[1591],errmsg[ORA-01591:
CEASYDAO: 错误码[1591],错误信息[Error - OCI_ERROE - errcode[1591],errmsg[ORA-01591: lock held by in-doubt d ...
- hdu 1715 大菲波数(高精度数)
Problem Description Fibonacci数列,定义如下: f(1)=f(2)=1 f(n)=f(n-1)+f(n-2) n>=3. 计算第n项Fibonacci数值. Inpu ...