题意:
判断最小树是否唯一。
思路:
我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生成树,就这样一直跑最小生成树,如果找到了一颗和之前的那个一样的,那么就是不唯一,第二种方法也是先最小树,然后枚举,在枚举的时候不是继续重新跑,而是断开当前边,把树分成两个集合<两次深搜实现>,然后在枚举这连个集合之间是否可以找到一个可以代替当前枚举的最小树的边,实现复杂度的话应该是第二种快点,但理论上也快不多少,只是为了练练手,在多说一句,第二种方法和求次小树的思路有点像,但是次小树可以再这个上面进行dp优化,其实这个题目也可以直接判断次小树是否等于最小树。好像有点说多了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110
using namespace std;
typedef struct
{
int x ,y ,c;
}EDGE;
EDGE edge[N*N];
int mer[N] ,mst[N];
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int MST(int n ,int m ,int co)
{
for(int i = 1 ;i <= n ;i ++)mer[i] = i;
int Ans = 0 ,sum = 0;
for(int i = 1 ;i <= m ;i ++)
{
if(i == co) continue;
int xx = finds(edge[i].x);
int yy = finds(edge[i].y);
if(xx != yy)
{
Ans += edge[i].c ,sum ++ ;
mer[xx] = yy;
if(co == -1) mst[sum] = i;
}
if(sum == n - 1) break;
}
return Ans;
}
int main ()
{
int t ,i ,n ,m;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c);
sort(edge + 1 ,edge + m + 1 ,camp);
int Ans = MST(n ,m ,-1);
for(i = 1 ;i < n ;i ++)
{
int tmp = MST(n ,m ,mst[i]);
if(Ans == tmp) break;
}
i == n || m == n - 1? printf("%d
" ,Ans) : puts("Not Unique!");
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110
using namespace std;
typedef struct
{
int x ,y ,c;
}EDGE;
typedef struct
{
int to ,next;
}STAR;
EDGE edge[N*N];
STAR E[N*N];
int map[N][N] ,mer[N] ,mark[N];
int list[N] ,tot ,mst[N];
int L[N] ,R[N] ,ll ,rr;
void add(int a, int b)
{
E[++tot].to = b;
E[tot].next = list[a];
list[a] = tot;
}
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int MST(int n ,int m)
{
for(int i = 1 ;i <= n ;i ++) mer[i] = i;
int Ans = 0 ,sum = 0;
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(int i = 1 ;i <= m ;i ++)
{
int xx = finds(edge[i].x);
int yy = finds(edge[i].y);
if(xx != yy)
{
Ans += edge[i].c ,sum ++;
mer[xx] = yy;
mst[sum] = i;
add(edge[i].x ,edge[i].y);
add(edge[i].y ,edge[i].x);
}
if(sum == n - 1) break;
}
return Ans;
}
void DFS1(int x)
{
for(int k = list[x] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]) continue;
mark[to] = 1;
L[++ll] = to;
DFS1(to);
}
}
void DFS2(int x)
{
for(int k = list[x] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]) continue;
mark[to] = 1;
R[++rr] = to;
DFS2(to);
}
}
int main ()
{
int t ,n ,m ,i ,j ,mk;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= n ;j ++)
map[i][j] = 100000000;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c);
int x = edge[i].x ,y = edge[i].y;
map[x][y] = map[y][x] = minn(map[x][y] ,edge[i].c);
}
sort(edge + 1 ,edge + m + 1 ,camp);
int Ans = MST(n ,m);
if(m == n - 1)
{
printf("%d
" ,Ans);
continue;
}
mk = 0;
for(i = 1 ;i < n && !mk;i ++)
{
memset(mark ,0 ,sizeof(mark));
int l = edge[mst[i]].x ,r = edge[mst[i]].y;
mark[l] = mark[r] = 1;
ll = rr = 0;
L[++ll] = l ,R[++rr] = r;
DFS1(l) ,DFS2(r);
for(int j = 1 ;j <= ll && !mk;j ++)
{
for(int k = 1 ;k <= rr && !mk ;k ++)
{
if(L[j] == edge[mst[i]].x && R[k] == edge[mst[i]].y || L[j] == edge[mst[i]].y && R[k] == edge[mst[i]].x)
continue;
if(map[L[j]][R[k]] == edge[mst[i]].c) mk = 1;
}
}
}
mk ? printf("Not Unique!
"): printf("%d
" ,Ans);
}
return 0;
}