GGS-DDU 【HDU - 4966】【最小樹形圖】
阿新 • • 發佈:2019-01-06
題目連結
最小樹形圖講解
一道最小樹形圖的裸題,我們只需要對於在同一學科的由高等級逐一指向低等級的邊建為0權值即可,另外的邊,建立成有向邊即可。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f using namespace std; typedef unsigned long long ull; typedef long long ll; int N, M, a[55], b[55][501], num_V, num_E, tot; struct Eddge { int u, v, val; Eddge(int a=0, int b=0, int c=0):u(a), v(b), val(c) {} }edge[250005]; int vis[1005], id[1005], pre[1005], in[1005]; int Dir_MST(int root, int V, int E) { int ans = 0; while(true) { for(int i=0; i<V; i++) in[i] = INF; for(int i=1; i<=E; i++) { int u = edge[i].u, v = edge[i].v; if(u != v && edge[i].val < in[v]) { in[v] = edge[i].val; pre[v] = u; } } for(int i=0; i<V; i++) { if(i == root) continue; if(in[i] == INF) return -1; } int cnt = 0; memset(id, -1, sizeof(id)); memset(vis, -1, sizeof(vis)); in[root] = 0; for(int i=0; i<V; i++) { ans += in[i]; int v = i; while(vis[v] != i && id[v] == -1 && v != root) { vis[v] = i; v = pre[v]; } if(v != root && id[v] == -1) { for(int u = pre[v]; u != v; u = pre[u]) id[u] = cnt; id[v] = cnt++; } } if(cnt == 0) break; for(int i=0; i<V; i++) if(id[i] == -1) id[i] = cnt++; for(int i=1; i<=E; i++) { int u = edge[i].u, v = edge[i].v; edge[i].u = id[u]; edge[i].v = id[v]; if(id[u] != id[v]) edge[i].val -= in[v]; } V = cnt; root = id[root]; } return ans; } void init() { num_E = num_V = 0; } int main() { while(scanf("%d%d", &N, &M) && (N || M)) { init(); for(int i=1; i<=N; i++) { scanf("%d", &a[i]); b[i][0] = ++num_V; for(int j=1; j<=a[i]; j++) { b[i][j] = ++num_V; edge[++num_E] = Eddge(num_V, num_V-1, 0); } } for(int i=1, e1, e2, e3, e4, e5; i<=M; i++) { scanf("%d%d%d%d%d", &e1, &e2, &e3, &e4, &e5); if(e2 == 0) edge[++num_E] = Eddge(0, b[e1][e2], 0); edge[++num_E] = Eddge(b[e1][e2], b[e3][e4], e5); } printf("%d\n", Dir_MST(0, num_V + 1, num_E)); } return 0; }