动漫节一游回来之后一直处于一种意识模糊的状态

看到大家都陆陆续续地过了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的更多相关文章

  1. codeforces 338(Div 2) B. Longtail Hedgehog 解题报告

    题目链接:http://codeforces.com/problemset/problem/615/B 题目意思:要画一只 hedgehog,由 tail 和 spines 组成.我们要求得 beau ...

  2. Codeforces Round #581(Div. 2)

    Codeforces Round #581(Div. 2) CF 1204 A. BowWow and the Timetable 题解:发现,$4$的幂次的二进制就是一个$1$后面跟偶数个$0$. ...

  3. Codeforces Round #433 (Div. 2)【A、B、C、D题】

    题目链接:Codeforces Round #433 (Div. 2) codeforces 854 A. Fraction[水] 题意:已知分子与分母的和,求分子小于分母的 最大的最简分数. #in ...

  4. 10-2 body标签中相关的标签(字体标签,排版标签(div,span),超链接,图片标签)

    一 排版标签(div,span) 1块级标签 <!--div:把标签中的内容作为一个块儿来对待(division).必须单独占据一行.--> <!--div标签的属性:--> ...

  5. 【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,输出任意方案. [算法]数学+搜索 [题解] 最关 ...

  6. Codeforces Round #334(div.2)(新增不用二分代码) B

    B. More Cowbell time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  7. 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 ...

  8. 网站常见问题及解决方法(div/css)

    18.<a> 在IE6,7 下面重新定义宽和高的代码:{  display:block; display:-moz-inline-stack; display:inline-block;  ...

  9. CodeForces - 589A(二分+贪心)

    题目链接:http://codeforces.com/problemset/problem/589/F 题目大意:一位美食家进入宴会厅,厨师为客人提供了n道菜.美食家知道时间表:每个菜肴都将供应. 对 ...

随机推荐

  1. 【递归】P2386放苹果

    题目相关 题目描述 把 m个同样的苹果放在 n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法.(5,1,1 和 1,1,5 是同一种方法) 输入格式 第一行是测试数据的数目 t,以下每行 ...

  2. Redis集群搭建与简单使用【转】

    Redis集群搭建与简单使用 安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都 ...

  3. 爬虫-urllib3模块的使用

    urllib3是一个功能强大,对SAP健全的 HTTP客户端,许多Python生态系统已经使用了urllib3. 一.安装 sudo pips install urllib3 二.创建PoolMana ...

  4. RPC 是通信协议吗 ?→ 我们来看下它的演进过程

    开心一刻 一实习小护士给我挂针,拿着针在我胳膊上扎了好几针也没找到血管 但这位小姑娘真镇定啊,表情严肃认真,势有不扎到血管不罢休的意思 十几针之后,我忍着剧痛,带着敬畏的表情问小护士:你这针法跟容嬷嬷 ...

  5. 更改mysql的密码

    mysql> set password for 'root'@'localhost' =PASSWORD('');Query OK, 0 rows affected (0.17 sec) mys ...

  6. 【老孟Flutter】源码分析系列之InheritedWidget

    老孟导读:这是2021年源码系列的第一篇文章,其实源码系列的文章不是特别受欢迎,一个原因是原理性的知识非常枯燥,我自己看源码的时候特别有感触,二是想把源码分析讲的通俗易懂非常困难,自己明白 和 让别人 ...

  7. 一文读懂 Kubernetes APIServer 原理

    前言 整个Kubernetes技术体系由声明式API以及Controller构成,而kube-apiserver是Kubernetes的声明式api server,并为其它组件交互提供了桥梁.因此加深 ...

  8. Databricks 第7篇:管理Secret

    有时,访问数据要求您通过JDBC对外部数据源进行身份验证,可以使用Azure Databricks Secret来存储凭据,并在notebook和job中引用它们,而不是直接在notebook中输入凭 ...

  9. postman接口测试之复制多个接口或collections到某个子文件夹或collections下

    一.痛点 1.postman只支持复制一个请求,或者一个子文件夹,但是不支持复制多个请求,或者整个collections到某个子文件夹或者某个collections下. 2.网上查了好一会儿,没有一个 ...

  10. jvm源码解析java对象头

    认真学习过java的同学应该都知道,java对象由三个部分组成:对象头,实例数据,对齐填充,这三大部分扛起了java的大旗对象,实例数据其实就是我们对象中的数据,对齐填充是由于为了规则分配内存空间,j ...