Graph_Master~(连通分量)

题目大意:给出m条边(隧道,无向),每条边连接两个点(矿场)。要在这些矿场中建设救援出口,防止矿场坍塌造成人员伤亡,问最少需要几个救援出口,以及对应方案数。(假设最多塌陷一个矿场)。

题解:这个题面给的数据比较良心,画画图知道需要找割点,然后把割点去掉跑连通块。也就是说每个连通块的颜色除了割点都是一样的,因为割点还属于别的连通块。紧接着就是统计答案了:

1、如果一个连通块没有割点,那么救援点至少建两个,方案数将乘上(这个连通块大小设为totv,包括割点)totv*(totv-1)/2,即C(2,totv)。建两个是以防如果只建一个,那个点坍塌了,就困死了,因为没有割点,就相当于是独立的,只能自生自灭。

2、如果一个连通块只有一个割点,那么救援点至少建一个,方案数乘上totv。因为如果割点坍塌,可以从救援点跑,如果救援点坍塌,可以从割点跑到另外的有救援点的连通块。

3、如果一个连通块有>=2个割点,不用建救援点,不用算方案数,因为不管怎么坍塌,都可以跑到别的有救援点的连通块。

(上图比较好理解)

图解:1、2、3、47、8、9、10即为仅有一个割点(割点分别为4、7)的连通块。

4、5、6、7为有两个割点(4、7)的连通块。

11、12、13、14为没有割点的连通块(独立出来的一部分)。

有了图解每个连通块应该建几个救援点,以及如何统计方案数可以说就比较清楚了。

WA了很多发,因为没有发现used[]开成了bool,而却是用于染色,应该开成int,太粗心了。可以看到数组都远超所给范围,因为前几天给坑怕了。。


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#define clr(a,b) memset((a),(b),sizeof(a))
using namespace std; const int N = 10005;
const int M = 1e6 + 16;
typedef long long ll; struct Edge
{
int nxt, u, v;
};
Edge edge[M]; int ecnt, head[N];
int low[N], dfn[N];
int dep, col, cut_sum, totv;
int used[N], iscut[N];
int rt; void init()
{
clr(head,-1);
clr(used,0);
clr(iscut,0);
clr(dfn,0);
clr(low,0);
ecnt = dep = col = 0;
} void _add( int a, int b )
{
edge[ecnt].u = a;
edge[ecnt].v = b;
edge[ecnt].nxt = head[a];
head[a] = ecnt ++;
} void tarjan( int u, int pr )
{
low[u] = dfn[u] = ++dep;
int son = 0;
for ( int i = head[u]; i+1; i = edge[i].nxt )
{
int v = edge[i].v;
if ( v == pr ) continue;
if ( !dfn[v] )
{
son ++;
tarjan( v, u );
low[u] = min( low[u], low[v] ); if ( low[v] >= dfn[u] )
iscut[u] = 1;
}
else
low[u] = min( low[u], dfn[v] );
}
if ( u == rt && son == 1 )
iscut[u] = 0;
} void dfs( int u )
{
used[u] = col;
totv ++;
for ( int i = head[u]; i+1; i = edge[i].nxt )
{
int v = edge[i].v;
if ( iscut[v] && used[v] != col )
{
cut_sum++;
used[v] = col;
}
else if ( !used[v] )
dfs( v );
}
} int main()
{
int m;
int cas = 1;
while ( scanf("%d", &m), m )
{
int n = 0;
init();
for ( int i = 0; i < m; i ++ )
{
int u, v;
scanf("%d%d", &u, &v);
_add(u,v);
_add(v,u);
n = max( n, max(u,v) );
} for ( int i = 1; i <= n; i ++ )
{
if ( !dfn[i] )
{
rt = i;
tarjan( i, -1 );
}
} int ans1 = 0;
ll ans2 = 1;
for ( int i = 1; i <= n; i ++ )
{
if ( !used[i] && !iscut[i] )
{
totv = cut_sum = 0;
col ++;
dfs( i );
if ( cut_sum == 0 )
{
ans1 += 2;
ans2 *= 1ll*totv*(totv-1)/2;
}
else if ( cut_sum == 1 )
{
ans1 ++;
ans2 *= 1ll*totv;
}
}
} printf("Case %d: %d %lld\n", cas++, ans1, ans2);
}
return 0;
}

Graph_Master(连通分量_G_Trajan+Thought)的更多相关文章

  1. Graph_Master(连通分量_H_Trajan+拓扑序dp)

    Graph_Master_连通分量_H 题目描述: 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条 ...

  2. Graph_Master(连通分量_Poj_1904)

    Poj_1904 背景:本来是在做Voj的连通分量,做到了E( hdu_4685 ),想到了二分图,但是笔者只会最大匹配,但题目要求要输出所有的最大匹配情况,想了好久都没想出来怎么做,因为如果我已知一 ...

  3. Graph_Master(连通分量_D_Trajan缩点+dfs)

    hdu_2242 题目大意:求将一张无向图(n个点,m条边)移除一条边分为不连通两部分,使得两部分的点权和最接近,若无法分为两部分,则输出impossible. 题解:拿到题面还算清晰,就是先tarj ...

  4. Graph_Master(连通分量_A_双连通分量+桥)

    hdu 5409 题目大意:给出一张简单图,求对应输入的m条边,第i-th条边被删除后,哪两个点不连通(u,v,u<v),若有多解,使得u尽量大的同时v尽量小. 解题过程:拿到题面的第一反应缩点 ...

  5. Graph_Master(连通分量_E_Hungry+Tarjan)

    hdu_4685 终于来写了这题的解题报告,没有在昨天A出来有点遗憾,不得不说数组开大开小真的是阻碍人类进步的一大天坑. 题目大意:给出n个王子,m个公主,只要王子喜欢,公主就得嫁(这个王子当得好霸道 ...

  6. Graph_Master(连通分量_C_Trajan缩点+最小路径覆盖)

    hdu_3861 题目大意:给定一张有向图,若<u,v>可达(u可以走到v,或者 v可以走到u),则<u,v>需被划分在统一城邦,问最小划分城邦数. 题解:比较裸的题,可以看出 ...

  7. Graph_Master(连通分量_B_Trajan+完全图)

    hdu_4635 题目大意:给出一张DAG(n个点,m条边),求出能加的最大边数,使得该图无重边,无自环,非强连通. 题解:这题题面很好理解,也没有什么很难的点,主要是如何求出最大边数需要动点脑筋.首 ...

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

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

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

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

随机推荐

  1. CentOS中文乱码问题的解决方法

    一.CentOS系统访问 xxx.cn ,发现中文乱码于是用以前的方式:# yum -y install fonts-chinese # yum -y install fonts-ISO8859 Ce ...

  2. 剑指Offer——和为S的连续正数序列

    题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...

  3. java基础03变量和基本数据类型

    package cn.bdqn.test; /** * * @author 小豆腐 * * 变量:会变化的量?? * 一个数据在内存中存储空间的表示!在运行期间可以动态改变! * * 关键字:在jav ...

  4. 三.插入和查找MySQL记录 数据类型

    1.插入数据的两种方式 1)INSERT tb1 VALUES('TOM',25,1863.25); 2)INSERT tb1(username,salary) VALUES('John',4500. ...

  5. 新建虚拟机与本机ping不通(一招解决)

    初始新建虚拟机或者复制虚拟机后,发现虚拟机能ping通内外网,但是本机无法ping通虚拟机,xshell也无法连接虚拟机 这时候就很头疼了,因为要上传很多文件到虚拟机上面 解决办法: 1.关闭虚拟机后 ...

  6. MongoDB的安全校验

    一.MongoDB安全校验的重要性 每个MongoDB实例中的数据库都可以有许多用户.如果没有开启安全校验,限制用户权限,则每个进到数据库的用户都能任意的对数据库数据进行读,写甚至是读写操作.这样的场 ...

  7. 工作笔记——区块链POC

    1.基础配置 安装SecureCRT 8.0链接到虚拟服务器,并配置docker 安装文件上传到服务器工具FileZilla

  8. cpu-》内存-》磁盘

    cpu相当于计算机大脑负责计算以及发送执行命令:内存相当于人的记忆是临时存储:磁盘相当于笔记本,负责永久存储数据: 当系统需要调用硬盘当中的数据时,会将硬盘数据读入内存供cpu进行处理.cpu只会读取 ...

  9. XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem D. Clones and Treasures

    题目:Problem D. Clones and TreasuresInput file: standard inputOutput file: standard outputTime limit: ...

  10. Unity本地数据存储---Sqlite和JSON

    2014-05-04更新 SqliteDatabase.cs这个文件的初始方法有问题,具体是如果指定URL已经存在了DB文件,就不会重新覆盖DB文件. 这导致我们修改之后的DB文件无法产生效果. 本人 ...