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

看到大家都陆陆续续地过了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. ASP.NET 上传文件到共享文件夹

    创建共享文件夹参考资料:https://www.cnblogs.com/dansediao/p/5712657.html 上传文件代码 web.config <!--上传文件配置,UploadP ...

  2. 【JDBC核心】数据库连接池

    数据库连接池 传统模式 使用数据库的传统模式: 在主程序(servlet.beans等)中建立数据库连接: 进行 SQL 操作: 断开数据库连接. 这种模式存在的问题: JDBC 连接数据库的方式(四 ...

  3. LeetCode106 从中序和后序序列构造二叉树

    题目描述: 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [ ...

  4. Flutter 应用入门:包管理

    pubspec.yaml name: flutter_combat description: A Flutter combat application. # The following defines ...

  5. leetcode-242有效字母异位词

    题目 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词. 示例 1: 输入: s = "anagram", t = "nagaram&quo ...

  6. 浅谈sql索引

    索引是什么 假如你手上有一个你公司的客户表,老板说找什么客户你就得帮他找出来. 客户不多的时候,你拿着手指一行一行滑,费不了多少时间就能找到. 后来公司做大了,客户越来越多,好几页的客户,你发现,一行 ...

  7. 基于 MapReduce 的单词计数(Word Count)的实现

    完整代码: // 导入必要的包 import java.io.IOException; import java.util.StringTokenizer; import org.apache.hado ...

  8. linux最大打开文件句柄数

    linux最大打开文件句柄数,即打开文件数最大限制,就是规定的单个进程能够打开的最大文件句柄数量(Socket连接也算在里面,默认大小1024) liunx中文件句柄有两个限制,一种是用户级的,一种是 ...

  9. 【Web】CSS中的浮动float

    CSS中的float 文章目录 CSS中的float 1.float浮动属性 2.float文字环绕图片 3.float浮动的真正原因以及副作用分析 4.清除浮动的四种解决方法 5.实际应用 导航效果 ...

  10. CSAPP:Lab0 -Docker搭建纯净Linux环境

    1. 安装docker 在mac-os下我们可以利用homebrew很容易的安装docker. brew install docker 当然去官网下载也很容易 Empowering App Devel ...