博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
杭电1827--Summer Holiday(SCC + 缩点)
阅读量:5913 次
发布时间:2019-06-19

本文共 2771 字,大约阅读时间需要 9 分钟。

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1827

 

第二道强连通分量题目, 对于SCC也有了一定的认识, 所以想在这里总结一下;有向非强连通图的极大强连通子图叫做强连通分量 (SCC), 所有强连通分量在原图中组成一个DAG(每个强连通分量看作一个点)。TarJan() 算法利用Dfs找强连通分量, 我们可以把Dfs搜索过程看作是一个整体,个人感觉分步模拟并不是很好理解。 

Low[]: 时间戳;(树根)。 

dfn[]; 记录搜索当前节点的时间。 

当搜索到强连通分量时, 让根节点及其以上节点弹出栈。(instack[u] = 0)。可以进行操作是记录SCC个数 && 缩点 && 记录SCC中结点的个数。

 

本题题意是在一个有向关系图中, 花最少的话费, 把消息通知到所有人。

看SCC入度 V, V!= 0 不需花费, V == 0, 取花费最少节点, 注意操作一致性。

 

#include 
#include
#include
#include
using namespace std;const int INF = 0x3f3f3f3f;int dfn[1001], low[1001], instack[1001], sccf[1001], Rdu[1001], Cost[1001], cnt_SCC, vis_num, total, n, m;struct Edge{ int from, to, next;} edge[2010];int cnt, head[1001];void Add(int a, int b){ Edge E = {a, b, head[a]}; edge[cnt] = E; head[a] = cnt++;}stack
S;void TarJan(int x){ int j; dfn[x] = low[x] = ++vis_num; instack[x] = 1; S.push(x); for(int i = head[x]; i != -1; i = edge[i].next) { int u = edge[i].to; if(dfn[u] == -1) { TarJan(u); if(low[x] > low[u]) low[x] = low[u]; } else if(instack[u] && low[x] > dfn[u]) low[x] = dfn[u]; } if(low[x] == dfn[x]) { cnt_SCC++; do{ j = S.top(); sccf[j] = cnt_SCC; S.pop(); instack[j] = 0; } while(j != x); }}void Deal() //确定结果; { for(int i = 1; i <= n; i++) { for(int k = head[i]; k != -1; k = edge[k].next) { int u = edge[k].to; if(sccf[u] != sccf[i]) Rdu[sccf[u]]++; } } int ReSult = 0; for(int i = 1; i <= cnt_SCC; i++) { if(!Rdu[i]) { ReSult++; int minn = INF; for(int j = 1; j <= n; j++) { if(sccf[j] == i) minn = min(minn, Cost[j]); } total += minn; } } printf("%d %d\n", ReSult, total);}void SolVe(){ vis_num = cnt_SCC = total = 0; for(int i = 1; i <= n; i++) if(dfn[i] == -1) TarJan(i);// printf("%d\n", cnt_SCC);} void GetMap(){ memset(Rdu, 0, sizeof(Rdu)); memset(low, 0, sizeof(low)); memset(dfn, -1, sizeof(dfn)); memset(head, -1, sizeof(head)); memset(instack, 0, sizeof(instack)); cnt = 0; for(int i = 1; i <= m; i++) { int a, b; scanf("%d %d", &a, &b); Add(a, b); }}int main(){ while(~scanf("%d %d", &n, &m)) { for(int i = 1; i <= n; i++) scanf("%d", &Cost[i]); GetMap(); SolVe(); Deal(); } return 0;}

 

转载于:https://www.cnblogs.com/soTired/p/4813210.html

你可能感兴趣的文章
深入Mysql - 谈谈我对数据类型的认识
查看>>
Tsuru 1.7.0-rc4 发布,基于 Docker 的 PaaS 框架
查看>>
Apache HBase 2.1.3 发布,分布式数据库
查看>>
微信端H5开发整体解决方案
查看>>
Python之retrying
查看>>
OWASP 10 大 Web 安全问题在 JEE 体系完全失控
查看>>
洛谷 P1640 BZOJ 1854 [SCOI2010]连续攻击游戏
查看>>
如何理解Unity组件化开发模式
查看>>
util.promisify 的那些事儿
查看>>
未来黑科技公司完成亿元Pre-B轮融资,已和宝马达成合作
查看>>
三篇文章了解 TiDB 技术内幕 - 谈调度
查看>>
【DG】DG的3种保护模式
查看>>
[20150107]关于print_table.txt
查看>>
Chrome 如何知道网站启用了SPDY 协议?
查看>>
8天玩转并行开发——第五天 同步机制(下)
查看>>
一次性关闭所有的Activity
查看>>
运算符 - PHP手册笔记
查看>>
二维数组的认识及其表示元素的两种方式
查看>>
LINUX下DNS的查看和配置
查看>>
分布式事务系列(1.2)Spring的事务体系
查看>>