您的位置:首页 > 其它

UVA 10600 ACM Contest and Blackout

2016-12-15 14:56 513 查看


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

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

#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
, nt
, u
, v
, sz, fa
, g

;

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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: