<题目链接>

题目大意:

有n个房间,每个房间都会有一只老鼠。处于第i个房间的老鼠可以逃窜到第ai个房间中。现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老鼠的最少花费。

解题分析:

首先就是要注意老鼠的逃生路线为强连通分量的情况,毫无疑问,这种情况就是在那个强连通分量中的代价最小的房间安装老鼠夹(因为根据老鼠的流通性,只需要在连通分量中安装一个老鼠夹就能捕获所有的老鼠),所以我们先用Tarjan对这些房间进行缩点。然后我们只需要将那些出度为0的强连通分量的代价相加就行(强连通分量的代价=其中任意点的最小代价),因为出度为0的强连通分量一定要消除本身的老鼠,并且根据老鼠的流通性,其它出度不为0的老鼠一定也会到达这些出度为0的连通分量中。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int INF =0x3f3f3f3f;
  5. #define N int(2e5+7)
  6. #define rep(i,s,t) for(int i=s;i<=t;i++)
  7. #define srep(i,s,t) for(int i=s;i<t;i++)
  8. #define clr(a,b) memset(a,b,sizeof(a))
  9. int n,top,ans,tot,scc;
  10. int outdeg[N],to[N],stk[N],instk[N],bel[N],dfn[N],low[N],cost[N],val[N];
  11.  
  12. template<typename T> //读入优化
  13. inline T read(T&x){
  14. x=;;char ch=getchar();
  15. ') f|=(ch=='-'),ch=getchar();
  16. +ch-',ch=getchar();
  17. return x=f?-x:x;
  18. }
  19. void Tarjan(int u){
  20. dfn[u]=low[u]=++tot;
  21. stk[++top]=u;instk[u]=;
  22. int v=to[u];
  23. if(!dfn[v]){
  24. Tarjan(v);
  25. low[u]=min(low[u],low[v]);
  26. }else if(instk[v])low[u]=min(low[u],dfn[v]);
  27. if(dfn[u]==low[u]){
  28. ++scc;
  29. while(true){
  30. int v=stk[top--];
  31. bel[v]=scc;
  32. if(u==v)break;
  33. }
  34. }
  35. }
  36. int main(){
  37. read(n);
  38. rep(i,,n)read(val[i]);
  39. rep(u,,n){
  40. int v;read(v);to[u]=v;
  41. }
  42. rep(i,,n) if(!dfn[i]){ //Tarjan缩点
  43. Tarjan(i);
  44. }
  45. rep(i,,scc)cost[i]=INF;
  46. rep(i,,n)cost[bel[i]]=min(cost[bel[i]],val[i]); //cost[i]为每个强连通分量中花费最少的点
  47. rep(u,,n){
  48. int v=to[u];
  49. if(bel[u]!=bel[v])outdeg[bel[u]]++; //标记每个强连通分量的出度
  50. }
  51. rep(i,,scc)if(!outdeg[i])ans+=cost[i]; //出度为0的点一定要安装(因为至少要消灭这些点本来的老鼠),并且只用安装出度为0的点,因为老鼠具有传递性,最终所有老鼠一定会经过这些出度为0的点
  52. printf("%d\n",ans);
  53. }

 另一种做法,用并查集判环,DFS找环上的最小代价:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. ;
  4. int to[N], val[N], pre[N], x[N];
  5. int find(int x){
  6. return x==pre[x]?x:pre[x]=find(pre[x]);
  7. }
  8. int dfs(int x, int root){
  9. if(x==root) return val[x]; //如果是自环,直接返回本身
  10. return min(dfs(to[x], root), val[x]); //寻找环上权值最小的点
  11. }
  12. int main(){
  13. int n;scanf("%d", &n);
  14. ;i<=n;i++)scanf("%d", &val[i]), pre[i] = i;
  15. ;i<=n;i++)scanf("%d", &to[i]);
  16. ;i<=n;i++){ //并查集判独立的连通块(判环或者判独立的点)
  17. ; //如果这个点存在环
  18. else pre[find(to[i])] = find(i);
  19. }
  20. ;
  21. ;i<=n;i++) if(x[i])ans+=dfs(to[i],i);
  22. printf("%d\n",ans);
  23. }

2019-02-18

Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)的更多相关文章

  1. Codeforces B. Mouse Hunt(强连通分解缩点)

    题目描述: Mouse Hunt time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  2. CodeForces - 455C Civilization (dfs+并查集)

    http://codeforces.com/problemset/problem/455/C 题意 n个结点的森林,初始有m条边,现在有两种操作,1.查询x所在联通块的最长路径并输出:2.将结点x和y ...

  3. 51nod 1456【强连通,缩点,并查集】

    话说这道题的机遇是看到了http://blog.csdn.net/u010885899/article/details/50611895很有意思:然后就去补了这题 题意: 建最少的边使得给出的点相连. ...

  4. DFS/并查集 Codeforces Round #286 (Div. 2) B - Mr. Kitayuta's Colorful Graph

    题目传送门 /* 题意:两点之间有不同颜色的线连通,问两点间单一颜色连通的路径有几条 DFS:暴力每个颜色,以u走到v为结束标志,累加条数 注意:无向图 */ #include <cstdio& ...

  5. Codeforces 745C:Hongcow Builds A Nation(并查集)

    http://codeforces.com/problemset/problem/744/A 题意:在一个图里面有n个点m条边,还有k个点是受限制的,即不能从一个受限制的点走到另外一个受限制的点(有路 ...

  6. Codeforces Educational Codeforces Round 5 C. The Labyrinth 带权并查集

    C. The Labyrinth 题目连接: http://www.codeforces.com/contest/616/problem/C Description You are given a r ...

  7. Codeforces Round #245 (Div. 2) B. Balls Game 并查集

    B. Balls Game Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/430/problem ...

  8. Codeforces Round #345 (Div. 1) E. Clockwork Bomb 并查集

    E. Clockwork Bomb 题目连接: http://www.codeforces.com/contest/650/problem/E Description My name is James ...

  9. POJ3694 Network 边双缩点+LCA+并查集

    辣鸡错误:把dfs和ldfs搞混...QAQ 题意:给定一个无向图,然后查询q次,求每次查询就在图上增加一条边,求剩余割边的个数. 先把边双缩点,然后预处理出LCA的倍增数组: 然后加边时,从u往上跳 ...

随机推荐

  1. with文件操作

    enumeratef = open('lyrics',"r",encoding=""utf-8) #文件句柄"""对文件操作流程 ...

  2. swift 实践- 04 -- UIButton

    import UIKit class ViewController: UIViewController { // 按钮的创建 // UIButtonType.system: 前面不带图标, 默认文字为 ...

  3. swift 实践- 02 -- 自定义cell 的简单使用

    import UIKit class MyTableViewCell: UITableViewCell { var imageV: UIImageView? var titleLabel: UILab ...

  4. STM32L476应用开发之五:数据保存与SD卡操作

    便携式气体分析仪的特点就是离线运行.尽管是离线运行,但测试数据还是需要的,所以采取方式保存数据就是必须的.在本次项目中我们计划采用SD卡来保存数据. 1.硬件设计 该读卡器整合 SD 卡规范和 FAT ...

  5. nikto for windows(web扫描工具) 使用教程

    本文出处: 欧普软件 ----------------------------------------------------------------------------------------- ...

  6. Confluence 6 删除垃圾内容

    属性(profile)垃圾 属性垃圾的定义为,一个垃圾用户在 Confluence 创建了用户,但是这个用户在自己的属性页面中添加了垃圾 URL. 如果你有很多垃圾用户在你的系统中创建了属性,你可以使 ...

  7. mysql服务器没有响应

    第一步删除c:\windowns下面的my.ini(可以先改成其它的名字也行) 第二步打开对应安装目录下\mysql\bin\winmysqladmin.exe 输入用户名 和密码(也可以忽略此步) ...

  8. eclipse php pdt插件安装

    安装动态语言工具包: help->new install software->work with 框输入 http://download.eclipse.org/technology/dl ...

  9. laravel 路由模型绑定

    我们在使用路由的时候一个很常见的使用场景就是根据资源 ID 查询资源信息: Route::get('task/{id}', function ($id) { $task = \App\Models\T ...

  10. Winhex数据恢复学习笔记(四)

    睡不着,那就深夜写篇笔记打发一下不瞌睡,❥(^_-) 1.winhex在文件批量处理上主要是针对批量保存.打开.关闭,主要还是基于批量打开的其他一些操作,这里通过构造通配符来批量打开,列如 *符号 ? ...