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. centos7通过阿里云配置docker加速镜像

    针对Docker客户端版本大于1.10.0的用户 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器: sudo mkdir -p /etc/docker s ...

  2. 正则表达式验证合法的IP地址

    IPv4地址 最初设计互联网络时,为了便于寻址和层次化构造网络,每个IP地址包括两个标识码(ID),即网络ID和主机ID.同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包括网络上的 ...

  3. 014-HQL中级4-Hive中的三种不同的数据导出方式介绍

    根据导出的地方不一样,将这些方式分为三种:(1).导出到本地文件系统:(2).导出到HDFS中:(3).导出到Hive的另一个表中.为了避免单纯的文字,我将一步一步地用命令进行说明. 一.导出到本地文 ...

  4. Java集合—集合框架

    前言 在Java语言中,Java语言的设计者对常用的数据结构和算法做了一些规范(接口)和实现(具体实现接口的类).所有抽象出来的数据结构和操作(算法)统称为Java集合框架(JavaCollectio ...

  5. index full scan和index fast full scan区别

    触发条件:只需要从索引中就可以取出所需要的结果集,此时就会走索引全扫描 Full Index Scan    按照数据的逻辑顺序读取数据块,会发生单块读事件, Fast Full Index Scan ...

  6. 我的Linux病毒追踪记录

    第一次自己一个人全权负责做游戏服务器,对于Linux安全并不太懂,所以就在昨天,服务器遭到了攻击,刚开始,只是发现服务器的带宽占满了,以为是带宽不够用,可是想想,弱联网游戏对带宽占用也不高啊而且带宽加 ...

  7. thunk函数

    1.函数参数求值的策略 a.传值策略(c语言) 传值策略就是在进入函数体之前将 参数计算之后 将参数的值传入到函数体之中. let x = 8 f(x + 1)//参数为 f(9)//传进去的值实际上 ...

  8. Https之秘钥交换过程分析

    一.概念回顾 A <------M------> B场景:A.B两个人之间通讯,A传输信息M给B,假定是在不安全的通路上传输. 1.明文传输 被中间人C拦截下来,可以随意篡改A发送给B的消 ...

  9. curl 命令返回json结构human readable

    在curl命令后面添加 | python -m json.tool 不想显示curl的统计信息,添加 -s参数 例: curl https://news-at.zhihu.com/api/4/news ...

  10. linux meta 18.0.1 系统安装nodejs

    前置条件是:需要准备sudo apt-get 命令 第一步: 执行命令sudo apt-get install nodejs 即可安装, 之后可使用node -v 查看版本node 版本号 第二步: ...