HDU3072

题意:

  给出n个点(0 - n-1),m条边,code从0开始需要传播到1 - (n-1)的每个点,强连通分量之间的传播是没有花费的,求最小花费。

思路:

  先计算出强连通分量,然后标出每个强连通分量的最小连通距离。即,它离其他任何一个强连通分量的最小距离。

  1 #include <bits/stdc++.h>
  2
  3 const int MAXN = 50000+10;
  4 const int MAXM = 100000+10;
  5 const int INF = 0x3f3f3f3f;
  6
  7 struct Edge
  8 {
  9     int v, cost, next;
 10     Edge() {}
 11     Edge(int _v, int _cost, int _next):v(_v), cost(_cost), next(_next){}
 12 } edge[MAXM];
 13 int tot;
 14
 15 int g[MAXN], dfn[MAXN], low[MAXN], T,ind,id[MAXN],dist[MAXN];
 16
 17 bool vis[MAXN];
 18 std::stack<int> sta;
 19
 20 void add_edge(int u, int v, int cost)
 21 {
 22     edge[tot] = Edge(v,cost,g[u]);
 23     g[u] = tot++;
 24 }
 25
 26 void tarjan(int u)
 27 {
 28     sta.push(u);
 29     vis[u] = true;
 30     dfn[u] = low[u] = T++;
 31     for(int i = g[u]; i != -1; i = edge[i].next) {
 32         int v = edge[i].v;
 33         if(!dfn[v]) {
 34             tarjan(v);
 35             low[u] = std::min(low[u], low[v]);
 36         }
 37         else if(vis[v] && low[u] > dfn[v])
 38             low[u] = dfn[v];
 39     }
 40     if(low[u] == dfn[u]) {
 41         ind++;
 42         int v;
 43         do {
 44             v=sta.top();
 45             sta.pop();
 46             id[v] = ind;
 47             vis[v] = false;
 48         }while(v != u);
 49     }
 50 }
 51
 52 void init()
 53 {
 54     memset(g, -1, sizeof g);
 55     memset(vis, 0, sizeof vis);
 56     memset(dfn,0, sizeof dfn);
 57     memset(low,0,sizeof low);
 58     T = ind = tot = 0;
 59     while(sta.empty() == false)
 60         sta.pop();
 61 }
 62
 63 int main()
 64 {
 65     int n, m;
 66     while(~scanf("%d%d", &n, &m) ){
 67         init();
 68         for(int i = 0, a, b, c; i<m; i++) {
 69             scanf("%d%d%d", &a, &b, &c);
 70             add_edge(a,b,c);
 71         }
 72
 73         // get all strongly connected component
 74         // and color them
 75         for(int i = 0; i < n; ++ i){
 76             if(dfn[i] == false){
 77                 tarjan(i);
 78             }
 79         }
 80         // dist[i] is the minimum distance between i and any other point
 81         for(int i = 0; i < ind; i++) {
 82             dist[i] = INF;
 83         }
 84         for(int i = 0; i < n; i++) {
 85             int u = id[i];
 86             for(int e = g[i]; e != -1; e = edge[e].next) {
 87                 int v = id[edge[e].v];
 88                 if(u != v) {
 89                     dist[v] = std::min(dist[v], edge[e].cost);
 90                 }
 91             }
 92         }
 93
 94         int res = 0;
 95         for(int i = 0; i < ind; ++ i) {
 96             if(i == id[0] || dist[i] == INF)
 97                 continue;
 98             res += dist[i];
 99         }
100         printf("%d\n", res);
101     }
102     return 0;
103 }
时间: 2024-10-25 16:09:37

HDU3072的相关文章

HDU3072 Intelligence System

题目传送门 有个中文版的题面...和原题稍有不同 /* Description “这一切都是命运石之门的选择.” 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短信,并由此得知了伦太郎制作出了电话微波炉(仮). 为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯网络,传达到所有分部. SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线路有一个固定的通讯花费Ci. 为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向另一个

hdu3072 强连通+最小树形图

题意:有一个人他要把一个消息通知到所有人,已知一些通知关系:A 能通知 B,需要花费 v,而又知道,如果某一个小团体,其中的成员相互都能直接或间接通知到,那么他们之间的消息传递是不需要花费的,现在问这个人将消息传给所有人所需的最小花费. 首先,一个团体中能够相互通知其实就是一个强连通分量,所以首先找出所有强连通分量,因为内部不需要花费,所以他们就相当于一个点,而早缩点之后,我们就得到了一张有向无环图,消息传递的最小花费其实就是最小树形图的边权和.刚做这个题的时候我还只是看见过最小树形图是什么,做

2016wust暑假集训之题解汇总2

数据结构 bzoj4546(可持久化Trie) 中文题题意我就不说了 解析: 可持久化Trie的模板题,详见注释 #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int maxbit=19; const int maxn=10500005; int tr[500002]; struct PerTrie { in

HDU-3072-IntelligenceSystem(tarjan,贪心)

链接:https://vjudge.net/problem/HDU-3072 题意: 给你n个点,1个点到另一个点连接花费c,但是如果几个点可以相互可达,则这几个点连通花费为0. 求将整个图连通的最小花费. 思路: tarjan,求出强连通子图. 对每个子图的进点的最小值更新,再累加即可,(不过不知道为什么) 代码: #include <iostream> #include <memory.h> #include <string> #include <istrea