51nod 1640 天气晴朗的魔法 最小生成树
题目链接:
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1640
题解:
先求最小生成树,记录最大边。
然后求最大生成树,保证所有边小于等于最小生成树的最大边。
#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<queue> using namespace std; typedef long long LL; const int maxn = 2e5 + 10; int n, m; struct Edge { int u, v, w; }egs[maxn]; bool cmp1(const Edge& e1, const Edge& e2) { return e1.w < e2.w; } bool cmp2(const Edge& e1, const Edge& e2) { return e1.w > e2.w; } int fat[maxn]; int Find(int x) { return fat[x] = fat[x] == x ? x : Find(fat[x]); } LL kruskal(int &ma,int sign) { for (int i = 0; i <= n; i++) fat[i] = i; LL ret = 0; for (int i = 0; i < m; i++) { int pu = Find(egs[i].u); int pv = Find(egs[i].v); if (pu != pv) { if (sign) { if (egs[i].w <= ma) { ret += egs[i].w; fat[pv] = pu; } } else { ma = max(ma, egs[i].w); fat[pv] = pu; } } } return ret; } int main() { while (scanf("%d%d", &n, &m) == 2 && n) { int ma = -1; for (int i = 0; i < m; i++) { scanf("%d%d%d", &egs[i].u, &egs[i].v, &egs[i].w); } sort(egs, egs + m, cmp1); kruskal(ma,0); sort(egs, egs + m, cmp2); LL ans = kruskal(ma,1); printf("%lld\n", ans); } return 0; }