题意 求n个点m条边的图的连通子图中最长边的最小值
实际上就是求最小生成树中的最长边 因为最小生成树的最长边肯定是所有生成树中最长边最小的 那么就也变成了最小生成树了 不要被样例坑到了 样例并不是最佳方案 只是最长边与最小生成树的最长边相等 题目是特判 直接用最小生成树做就行
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005, M = 15005;
struct edge{int u, v, w;} e[M];
int par[N], ea[N], n, m, num, ans;
bool cmp(edge a, edge b){ return a.w < b.w; }
int Find(int x)
{
int r = x, tmp;
while(par[r] >= 0) r = par[r];
while(x != r)
{
tmp = par[x];
par[x] = r;
x = tmp;
}
return r;
}
void Union(int u, int v)
{
int ru = Find(u), rv = Find(v), tmp = par[ru] + par[rv];
if(par[ru] > par[rv])
par[ru] = rv, par[rv] = tmp;
else
par[rv] = ru, par[ru] = tmp;
}
void kruskal()
{
memset(par, -1, sizeof(par));
for(int i = 1; i <= m; ++i)
{
int u = e[i].u, v = e[i].v;
if(Find(u) != Find(v))
{
ea[++num] = i;
ans = max(ans, e[i].w);
Union(u, v);
}
if(num >= n - 1) break;
}
}
int main()
{
int u, v, w;
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= m; ++i)
{
scanf("%d%d%d", &u, &v, &w);
e[i].u = u, e[i].v = v, e[i].w = w;
}
sort(e + 1, e + m + 1, cmp);
ans = num = 0;
kruskal();
printf("%d\n%d\n", ans, num);
for(int i = 1; i <= num; ++i)
{
int j = ea[i];
printf("%d %d\n", e[j].u, e[j].v);
}
}
return 0;
}
Description
Input
Output
Sample Input
4 6
1 2 1
1 3 1
1 4 2
2 3 1
3 4 1
2 4 1
Sample Output
1
4
1 2
1 3
2 3
3 4
POJ 1861 Network(隐含最小生成树 打印方案)
原文地址:http://blog.csdn.net/acvay/article/details/40373291