/* *State: HDU3072 328MS 2648K 2039 B C++ *题目大意: * 有一个含边权有向图,然后有向图中的强连通分量里面通信不需要 * 权值,要求从0点开始向所有的点通信,然后求最后总权值最小。 *解题思路: * 看到强连通分量不需要权值即可通信,就想到缩点。缩点之后就是一个 * DAG,然后这个DAG里面的除了起始点0之外,所有点都要走一次,那么 * 想清楚了其实就是每一个点有多条入度边,只需要找其中权值最小的 * 一条入度边即可,然后实现这个过程可以在缩点的过程中实现。 *解题感想; * 一看到这道题,由于心急,还是没有分析清楚,所以还搞了个spfa.这样 * 是不行的,也证明了自己学的算法少,学的算法都不够熟练,肚子里面的 * 墨水太少了。 */
View Code
#include <iostream> #include <vector> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int MAXN = 50005; const int MAXE = 100005; const int inf = 0x3f3f3f3f; typedef struct _node { int v, next, w; }N; N edge[MAXE]; int head[MAXN], cntEdge, dfn[MAXN], low[MAXN]; int step, top, inS[MAXN], myS[MAXN]; int scc, id[MAXN]; void init() { scc = 1; cntEdge = top = step = 0; for(int i = 0; i < MAXN; i++) { inS[i] = 0; head[i] = low[i] = dfn[i] = -1; } } void addEdge(int u, int v, int w) { edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].next = head[u]; head[u] = cntEdge++; } void tarjan_scc(int n) { dfn[n] = low[n] = ++step; myS[top++] = n; inS[n] = 1; for(int f = head[n]; f != -1; f = edge[f].next) { int son = edge[f].v; if(dfn[son] == -1) { tarjan_scc(son); low[n] = min(low[n], low[son]); } else if(inS[son] == 1) low[n] = min(low[n], dfn[son]); } if(low[n] == dfn[n] && top != 0) { int tmp; do { tmp = myS[--top]; id[tmp] = scc; inS[tmp] = 0; }while(top != 0 && tmp != n); scc++; } } void bulid_ADG(int n, int &sol) { int u, v, w; int edge_cost[MAXN]; for(int i = 0; i < n; i++) edge_cost[i] = inf; for(int i = 0; i < n; i++) { for(int f = head[i]; f != -1; f = edge[f].next) { u = i, v = edge[f].v, w = edge[f].w; if(id[u] == id[v]) continue; else { if(w < edge_cost[id[v]]) edge_cost[id[v]] = w; } } } sol = 0; for(int i = 1; i < scc; i++) { if(id[0] == i) continue; sol += edge_cost[i]; } } //注意题目有重边 int main(void) { #ifndef ONLINE_JUDGE freopen("inHDU3072.txt", "r", stdin); #endif int n, m; while(scanf("%d %d", &n, &m) == 2) { init(); int u, v, w; for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); addEdge(u, v, w); } tarjan_scc(0); int sol; bulid_ADG(n, sol); printf("%d\n", sol); } return 0; }