這道題很唬人的,題目描述說了那麼長,開始還給出了很多不要的輸入,但是仔細讀題,第二個輸出數字,是指M+K條邊裡面選擇幾條邊,串連,是費用最小,其實就是把之前的費用加起來,然後再在M+K的情況下求一次最小產生樹
還有,資料很大,數組果斷不要用了,只能用vector表示的邊表,其中裡面還有的資料結構還是結構體
稠密圖,邊最多可達到10的11次冪,雖說,有些網友表示,測試資料其實並沒有那麼大,但prim明顯會更合適
代碼:
#include <cstdio>#include <cstring>#include <vector>using namespace std;const int N = 1000001;const int INF = 1000000000;struct edge { int to, c; };vector <edge> vec[N];int n, m, k, tre1;int prim() { int mi, v, tre2 = 0; vector<int> d; d.push_back(INF); d.push_back(0); for ( int i = 2; i <= n; ++i ) d.push_back(INF); bool vis[N]; memset(vis, 0, sizeof(vis)); for ( int u = 0; u < n; ++u ) { mi = INF; for ( int i = 1; i <= n; ++i ) if ( !vis[i] && d[i] < mi ) mi = d[i], v = i; vis[v] = true; tre2 += mi; for ( int i = 0; i < vec[v].size(); ++i ) { int x = vec[v][i].to, cost = vec[v][i].c; if ( !vis[x] && d[x] > cost ) d[x] = cost; } } return tre2;}int main(){ bool flag = false; while ( scanf("%d", &n) != EOF ) { if ( flag ) printf("\n"); flag = true; tre1 = 0; for ( int i = 1, x, y, z; i < n; tre1 += z, ++i ) scanf("%d%d%d", &x, &y, &z); scanf("%d", &k); for ( int i = 0; i <= n; ++i ) vec[i].clear(); for ( int i = 0; i < k; ++i ) { int s, e, c; edge x; scanf("%d%d%d", &s, &e, &c); x.to = e, x.c = c; vec[s].push_back(x); x.to = s, x.c = c; vec[e].push_back(x); } scanf("%d", &m); for ( int i = 0; i < m; ++i ) { int s, e, c; edge x; scanf("%d%d%d", &s, &e, &c); x.to = e; x.c = c; vec[s].push_back(x); x.to = s; vec[e].push_back(x); } printf("%d\n", tre1); printf("%d\n", prim()); }}