这道题很唬人的,题目描述说了那么长,开始还给出了很多不要的输入,但是仔细读题,第二个输出数字,是指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());
}
}