题目链接
看到这道题的时候我心里一惊,求不同的最小生成树!我的天呐,然后又看到这么多人过了,一想,一定是简单的题,然后就用Kruskal做了个不同边的等价值降序/升序链接边的端点的序号快排处理,然后加上个两次Kruskal果然是这样!就这样过了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 105;
int N, M, root[maxN], fa[maxN];
ll ans;
bool vis[maxN];
struct Eddge
{
int no, to, val, id;
Eddge(int a=0, int b=0, int c=0, int d=0):no(a), to(b), val(c), id(d) {}
}a[maxN*maxN], b[maxN*maxN];
bool cmp_up(Eddge e1, Eddge e2)
{
if(e1.val == e2.val) return e1.no == e2.no?(e1.to<e2.to):(e1.no<e2.no);
else return e1.val<e2.val;
}
bool cmp_down(Eddge e1, Eddge e2)
{
if(e1.val == e2.val) return e1.no == e2.no?(e1.to>e2.to):(e1.no>e2.no);
else return e1.val<e2.val;
}
void init()
{
ans = 0;
for(int i=1; i<=N; i++) { root[i] = fa[i] = i; vis[i] = false; }
}
int fid(int x) { return x==root[x]?x:(root[x] = fid(root[x])); }
int father(int x) { return x==fa[x]?x:(fa[x] = father(fa[x])); }
void Kruskal_A()
{
for(int i=1; i<=M; i++)
{
int x = a[i].no, y = a[i].to, val = a[i].val;
int u = fid(x), v = fid(y);
if(u != v)
{
root[u] = v;
ans += val;
vis[a[i].id] = true;
}
}
}
bool Kruskal_B()
{
for(int i=1; i<=M; i++)
{
int x = b[i].no, y = b[i].to;
int u = father(x), v = father(y);
if(u != v)
{
fa[u] = v;
if(!vis[b[i].id]) return false;
}
}
return true;
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d%d", &N, &M);
init();
for(int i=1; i<=M; i++)
{
scanf("%d%d%d", &a[i].no, &a[i].to, &a[i].val);
if(a[i].no > a[i].to) swap(a[i].no, a[i].to);
a[i].id = i;
b[i] = a[i];
}
sort(a+1, a+1+M, cmp_up);
sort(b+1, b+1+M, cmp_down);
Kruskal_A();
if(Kruskal_B()) printf("%lld\n", ans);
else printf("Not Unique!\n");
}
return 0;
}