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道菜.美食家知道时间表:每个菜肴都将供应. 对 ...
随机推荐
- 免费、开源的基于tp5的快速开发框架
HisiPHP 系统官网:https://www.hisiphp.com/ 后台体验:http://v2.demo.hisiphp.com/admin.php/system/publics/index ...
- nginx: [emerg] bind() to 0.0.0.0:80 failed (10013:
问题出现 今天在win10安装nginx时候,启动nginx.exe时在dos窗口出现了这个错误,特此记录一下. 解决方法 上面报错信息的意思大概是:0.0.0:80地址访问不被允许.可能是80端口号 ...
- maven生命周期与插件
目录 Maven生命周期 clean default site 命令与对应周期 插件与绑定 插件目标 插件绑定 内置绑定 自定义绑定 插件配置 本文主要是针对<maven实战>书中关键知识 ...
- .NET探索平台条件编译
前言 今天偶然机会,翻了一下大学期间的书籍<C程序设计>,好吧,当我翻着翻着,翻到了符号常量(#define指令)中,是啊,这是一个预处理器指令,记得在Magicodes.IE中针对平台选 ...
- 【Linux】1、命令行及命令参数
命令行及命令参数 文章目录 命令行及命令参数 1.命令行提示符 2.命令和命令参数 简单的命令 date ls 命令参数 短参数(一个字母) 长参数(多个字母) 参数的值 其它参数 3.小结 4.参考 ...
- innodb是怎么刷新日志缓冲的
当innodb把日志缓冲刷新到磁盘日志文件的时候,先会用一个mutex锁住缓冲区,刷新到所需要的位置,然后移动剩下的条目到缓冲区的前面,当mutex释放时,可能有超过一个事务已经准备好刷新其日志记录, ...
- 【Docker】runtime create failed: container_linux.go:345: 解决
------------------------------------------------------------------------------------------------- | ...
- Python eval 函数用途
Python eval 函数用途: eval 函数可将字符串转换成列表,元组和字典 实例如下: 可以把list,tuple,dict和string相互转化. ##################### ...
- Nginx基础环境搭建
1.下载docker toolbox https://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/ 2.选择好安装目录 一路nex ...
- 1.2V转3.3V芯片电路图,超简电路
镍氢可充电电池1.2V转成3.3V的电路和电子产品很多,在实际适用中,即使是两节镍氢电池串联供电也是会有供电电压下降和不稳定的影响,这是因为电池电量减少,而导致电池的电压也是会随着降低. 一般情况下, ...