UVA 10600 ACM Contest and Blackout

来源:互联网 发布:matlab r2013a mac 编辑:程序博客网 时间:2024/05/16 10:48

求最小和次小生成树的权值和,先求出最小生成树,然后枚举剩下的边,判断如果用这条作为替代得到的生成树里,最小的那个是次小。

因为点数很少,可以直接暴力的求出全图所有点之间的最大边。

#include<cmath>  #include<queue>  #include<cstdio>  #include<cstring>  #include<algorithm>  using namespace std;#define ms(x,y) memset(x,y,sizeof(x))  #define rep(i,j,k) for(int i=j;i<=k;i++)  #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])  #define inone(x) scanf("%d",&x)  #define intwo(x,y) scanf("%d%d",&x,&y)  #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)  #define lson x<<1,l,mid  #define rson x<<1|1,mid+1,r  const int N = 1e3 + 10;const int M = 1e5 + 10;const int INF = 0x7FFFFFFF;int T, n, m, ans;int x[M], y[M], z[M], a[M], f[M];int ft[N], nt[N], u[N], v[N], sz, fa[N], g[N][N];int get(int x) { return x == fa[x] ? x : fa[x] = get(fa[x]); }bool cmp(int u, int v) { return z[u] < z[v]; }void dfs(int g[], int x, int y){loop(i, ft[x], nt){if (u[i] == y) continue;g[u[i]] = max(g[x], v[i]);dfs(g, u[i], x);}}int main(){inone(T);while (T--){intwo(n, m);rep(i, 1, m) inthr(x[i], y[i], z[i]), a[i] = i, f[i] = 0;sort(a + 1, a + m + 1, cmp);rep(i, 1, n) fa[i] = i, ft[i] = -1;int ans = sz = 0;rep(i, 1, m){int fx = get(x[a[i]]), fy = get(y[a[i]]);if (fx == fy) continue;fa[fx] = fy, ans += z[a[i]], f[i] = 1;u[sz] = y[a[i]]; v[sz] = z[a[i]]; nt[sz] = ft[x[a[i]]]; ft[x[a[i]]] = sz++;u[sz] = x[a[i]]; v[sz] = z[a[i]]; nt[sz] = ft[y[a[i]]]; ft[y[a[i]]] = sz++;}rep(i, 1, n) g[i][i] = 0, dfs(g[i], i, 0);int res = INF;rep(i, 1, m){if (f[i]) continue;res = min(res, ans + z[a[i]] - g[x[a[i]]][y[a[i]]]);}printf("%d %d\n", ans, res);}return 0;}


0 0