标签:app ati sample enter exchange new else tac turn
3 3 0 1 100 1 2 50 0 2 100 3 3 0 1 100 1 2 50 2 1 100 2 2 0 1 50 0 1 100
150 100 50
问从给定的节点0向其它全部的点通信,所花费的最小代价是多少?
思路:假设这两个点之间相互可达(直接简单介绍均可),代价为 0,即在一个SCC中的点连接的代价为0。所以首先SCC缩点新构图, 形成一个DAG图(有向无环图)。注意:一个SCC内的点相互连接是不须要花费的。可是连接两个SCC是要花费的,所以我们要在每一个SCC中找到花费最小的点最为整个SCC的花费,这样我们连接全部的SCC时花费才最小。
还要注意,0点所在的SCC花费为0。
#include <cstdio> #include <cstring> #include <algorithm> #define maxn 50000 + 5000 #define maxm 100000 + 10000 #define INF 0x3f3f3f3f using namespace std; int n, m; struct node { int u, v, w, next; }; node edge[maxm]; int head[maxn], cnt; int low[maxn], dfn[maxn]; int dfs_clock; int Stack[maxn], top; bool Instack[maxn]; int Belong[maxn]; int scc_clock; int num[maxn];//记录每一个缩点的花费。 void init(){ cnt = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int w){ int i; for(i = head[u]; i != -1; i = edge[i].next){ if(edge[i].v == v) break; } if(i == -1){ edge[cnt] = {u, v, w, head[u]}; head[u] = cnt++; } else//有重边,更新这条边最小的花费 edge[i].w = min(edge[i].w, w); } void getmap(){ int a, b, c; while(m--){ scanf("%d%d%d", &a, &b, &c); a++, b++; addedge(a, b, c); } } void Tarjan(int u){ int v; low[u] = dfn[u] = ++dfs_clock; Stack[top++] = u; Instack[u] = true; for(int i = head[u]; i != -1; i = edge[i].next){ v = edge[i].v; if(!dfn[v]){ Tarjan(v); low[u] = min(low[u], low[v]); } else if(Instack[v]) low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u]){ scc_clock++; do{ v = Stack[--top]; Instack[v] = false; Belong[v] = scc_clock; } while(v != u); } } void find(){ memset(low, 0, sizeof(low)); memset(dfn, 0, sizeof(dfn)); memset(Belong, 0, sizeof(Belong)); memset(Stack, 0, sizeof(Stack)); memset(Instack, false, sizeof(false)); dfs_clock = scc_clock = top = 0; for(int i = 1; i <= n ; ++i){ if(!dfn[i]) Tarjan(i); } } void suodian(){ for(int i = 1; i <= scc_clock; ++i) num[i] = INF; for(int i = 0; i < cnt; ++i){ int u = Belong[edge[i].u]; int v = Belong[edge[i].v]; if(u != v){ //跟新每一个缩点的最小花费 num[v] = min(num[v], edge[i].w); } } } void solve(){ int ans = 0; //printf("%d\n", scc_clock); for(int i = 1; i <= scc_clock; ++i){ //printf("%d\n", num[i]); if(Belong[1] != i) ans += num[i]; } printf("%d\n", ans); } int main (){ while(scanf("%d%d", &n, &m) != EOF){ init(); getmap(); find(); suodian(); solve(); } return 0; }
HDU 3072--Intelligence System【SCC缩点新构图 && 求连通全部SCC的最小费用】
标签:app ati sample enter exchange new else tac turn
原文地址:http://www.cnblogs.com/yutingliuyl/p/7018166.html