codeforces#244(div.2) C
动漫节一游回来之后一直处于一种意识模糊的状态
看到大家都陆陆续续地过了C心里还是有点着急(自己没思路啊囧)
其实当时就在想该如何找到DFS中的一个环,然后再找到环路上最小的一个值
把所有环路上最小的值加起来就是结果,后来看到有人在群里说是tarjan求强连通分量,我就愉(bei)快(shang)地去睡觉了
第二天起来就学习了一下强连通分量的相关知识和tarjan,现在整理下思路
https://www.byvoid.com/blog/scc-tarjan
tarjan的思路就是通过DFS找到一条环路,将以DFS访问的顺序的节点盖上时间戳,当该点u时间戳与该点(直接或间接)能够访问到的最早入栈的点相同(即可以说成是自身就是该子树的根)时,即表示它就是一个强连通量的根节点。我们不妨直接找到树中的一个“叶子”(姑且这么叫吧,把这里的“叶子”定义为除了栈S中的节点不能到达其他任何节点的节点(好绕囧))节点v,那么它只有两种可能:
1.可以在未处理节点的栈S中找到一个V使得(v,V)∈E,因此可以由V出发到v构成一个环路
2.不可以在未处理节点的栈S中找到一个V使得(v,V)∈E,因此它自成一个强连通分量(因为它不能到达任何的节点)(上述称为判断1)
如果讨论清楚了“叶子”节点,它必然成为某一个强连通分量中的一个顶点;再讨论栈中v的上一个节点u(即(u,v)∈E,且u∈栈S)
1.若为上述情况1,则根据上述链接和大白书上的定理,u,v必在同一个强连通分量中
2.若为上述情况2,则可以通过DFS找到u的其他后继vi:
(1)若vi存在,则继续用判断1判断有后继(祖先)在S中
(2)若vi不存在,则说明u没有其他后继了(自然也没有在栈S中的后继),则u可以通过上述情况2,u自成一个强连通分量
至此,证明完毕。可以保证,在栈S中的节点必然是以U为根“最大”(不知道这样说准不准确)的强连通量(因为不满足的已经被标记上强连通序号且弹出栈了)。
此说明是基于所有不属于以U为根的强连通分量的顶点已经被标记且弹出栈了。
上述描述即是以DFS序来进行描述的。
OK,回到这道题,如果找到了一个强连通分量,则可以统计出它的最小权值和最小权值点的个数
总的方案数就是所有强连通分量中的最小权值点个数的乘积
下面是C题的程序
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long LL;
const int SIZEN=100005;
const int SIZEM=300005;
const int INF=1e9;
const int MOD=1e9+7;
struct edge{
int to,next;
};
edge e[SIZEM];
int cost[SIZEN],head[SIZEN];
int DFN[SIZEM],low[SIZEN],sscn[SIZEN];
LL sz,s_cost,num_cost,dfs_time,ssc_cnt;
void addedge(int u,int v){
e[sz].to=v;
e[sz].next=head[u];
head[u]=sz++;
}
void init(){
memset(DFN,0,sizeof(DFN));
memset(low,0,sizeof(low));
memset(sscn,0,sizeof(sscn));
memset(head,-1,sizeof(head));
sz=0;num_cost=1;s_cost=0;
dfs_time=1;ssc_cnt=0;
}
stack<int> S;
void tarjan(int u){
DFN[u]=low[u]=dfs_time++;
S.push(u);
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(!DFN[v]){
tarjan(v);
low[u]=min(low[u],low[v]);//回溯过程,如果low[v]<low[u],则必然是因为v的某子孙和u的某祖先相连
}
else if(DFN[v]&&!sscn[v]){
low[u]=min(low[u],DFN[v]);//即上述判断1的情况1(找到后继在S中)
}
}
if(DFN[u]==low[u]){//找到一个强连通分量,找到分量中的最小值,和最小值的个数
int x;
int Min=INF,cnt=0;
ssc_cnt++;
for(;;){
x=S.top();S.pop();
sscn[x]=ssc_cnt;
if(cost[x]<Min){
Min=cost[x];
cnt=1;
}
else if(cost[x]==Min) cnt++;
if(x==u) break;
}
s_cost=s_cost+Min;num_cost=(LL)num_cost*cnt%MOD;
}
}
int main()
{
//freopen("data.in","r",stdin);
int i,j;
int n,m;
int u,v;
while(scanf("%d",&n)!=EOF){
init();
for(i=1;i<=n;i++) scanf("%d",&cost[i]);
scanf("%d",&m);
while(m--){
scanf("%d%d",&u,&v);
addedge(u,v);
}
for(i=1;i<=n;i++)
if(!DFN[i]) tarjan(i);
printf("%I64d %I64d\n",s_cost,num_cost);
}
return 0;
}
codeforces#244(div.2) C的更多相关文章
- codeforces 338(Div 2) B. Longtail Hedgehog 解题报告
题目链接:http://codeforces.com/problemset/problem/615/B 题目意思:要画一只 hedgehog,由 tail 和 spines 组成.我们要求得 beau ...
- Codeforces Round #581(Div. 2)
Codeforces Round #581(Div. 2) CF 1204 A. BowWow and the Timetable 题解:发现,$4$的幂次的二进制就是一个$1$后面跟偶数个$0$. ...
- Codeforces Round #433 (Div. 2)【A、B、C、D题】
题目链接:Codeforces Round #433 (Div. 2) codeforces 854 A. Fraction[水] 题意:已知分子与分母的和,求分子小于分母的 最大的最简分数. #in ...
- 10-2 body标签中相关的标签(字体标签,排版标签(div,span),超链接,图片标签)
一 排版标签(div,span) 1块级标签 <!--div:把标签中的内容作为一个块儿来对待(division).必须单独占据一行.--> <!--div标签的属性:--> ...
- 【CodeForces】841D. Leha and another game about graph(Codeforces Round #429 (Div. 2))
[题意]给定n个点和m条无向边(有重边无自环),每个点有权值di=-1,0,1,要求仅保留一些边使得所有点i满足:di=-1或degree%2=di,输出任意方案. [算法]数学+搜索 [题解] 最关 ...
- Codeforces Round #334(div.2)(新增不用二分代码) B
B. More Cowbell time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- Vus the Cossack and Strings(Codeforces Round #571 (Div. 2))(大佬的位运算实在是太强了!)
C. Vus the Cossack and Strings Vus the Cossack has two binary strings, that is, strings that consist ...
- 网站常见问题及解决方法(div/css)
18.<a> 在IE6,7 下面重新定义宽和高的代码:{ display:block; display:-moz-inline-stack; display:inline-block; ...
- CodeForces - 589A(二分+贪心)
题目链接:http://codeforces.com/problemset/problem/589/F 题目大意:一位美食家进入宴会厅,厨师为客人提供了n道菜.美食家知道时间表:每个菜肴都将供应. 对 ...
随机推荐
- Linux性能相关命令
Linux性能相关命令 目录 Linux性能相关命令 1. 查看硬盘相关信息 2. 查看CPU相关信息 3. 查看内存相关信息 4. 查看进程运行的信息 1. 查看硬盘相关信息 cat /proc/s ...
- 关于maven多module的依赖问题
之前的项目因为历史的原因,都是一个project里只包含了一个module,今年进入了新的项目组,出现了多个module,最近刚好也是在学<maven实战>因此想要将这个东西记录下来 工程 ...
- Log4j配置按照文件大小和日期分割日志文件
目录 Log4j 下载地址 文件大小分割日志文件 以日期分割每天产生一个日志文件 自定义信息输出到日志文件 Log4j 下载地址 Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控 ...
- 【Spring】创建一个Spring的入门程序
3.创建一个Spring的入门程序 简单记录 - Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)- Spring的基本应用 Spring与Spring MVC的 ...
- Mybatis 一级缓存和二级缓存的使用
目录 Mybatis缓存 一级缓存 二级缓存 缓存原理 Mybatis缓存 官方文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache My ...
- 当spring 对象@Autowired 注入失败或者创建对象Bean失败、No qualifying bean/Error creating bean 的失败情形分析和解决方案
错误信息 今天开发的过程中突然出现如下错误: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: N ...
- 爬虫学习(二)requests模块的使用
一.requests的概述 requests模块是用于发送网络请求,返回响应数据.底层实现是urllib,而且简单易用,在python2.python3中通用,能够自动帮助我们解压(gzip压缩的等) ...
- 边缘计算k8s集群SuperEdge初体验
前言 手上一直都有一堆的学生主机,各种各样渠道途径拿来的机器. 一直管理里面都比较蛋疼,甚至也不太记得住它们在哪是什么IP,管理起来很是头疼. 有阵子空闲的时候想折腾了一下边缘计算集群方案. 希望能把 ...
- Percona Toolkit工具使用
Percona Toolkit简称pt工具-PT-Tools,是Percona公司开发用于管理MySQL的工具,功能包括检查主从复制的数据一致性.检查重复索引.定位IO占用高的表文件.在线DDL等 下 ...
- 阿里云 CentOS7中搭建FTP服务器
1配置 vsftpd-3.0.2-27.el7.x86_64 阿里云 centos 7.0 2 ftp工作模式 2.1 ftp通道 ftp工作会启动两个通道: 控制通道,数据通道 在ftp协议中,控制 ...