poj 1679 The Unique MST(次小生成树)

题意:判断最小生成树是否唯一。

分析:只需要判断最小生成树与次小生成树的总权值是否相等。

判断次小生成树的方法:

kruskal O(n^3):先求一次最小生成树,然后枚举去掉生成树中的边,再求n-1次最小生成树,去最小的一棵。

prim O(n^2):先求一次最小生成树,记录树上的边,并且保存每个环中的最大边,然后用一次DP枚举掉树上的边,更新生成树的权和,取最小值。

kruskal
  1 /*

  2 Author:Zhaofa Fang

  3 Lang:C++

  4 */

  5 #include <cstdio>

  6 #include <cstdlib>

  7 #include <sstream>

  8 #include <iostream>

  9 #include <cmath>

 10 #include <cstring>

 11 #include <algorithm>

 12 #include <string>

 13 #include <utility>

 14 #include <vector>

 15 #include <queue>

 16 #include <stack>

 17 #include <map>

 18 #include <set>

 19 using namespace std;

 20 

 21 typedef long long ll;

 22 #define DEBUG(x) cout<< #x << ':' << x << endl

 23 #define REP(i,n) for(int i=0;i < (n);i++)

 24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)

 25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)

 26 #define PII pair<int,int>

 27 #define PB push_back

 28 #define MP make_pair

 29 #define ft first

 30 #define sd second

 31 #define lowbit(x) (x&(-x))

 32 #define INF (1<<30)

 33 

 34 

 35 const int maxn = 5050;

 36 int pa[111],a[111];

 37 struct Edge

 38 {

 39     int u,v,w;

 40 }edge[maxn];

 41 

 42 bool cmp(Edge x,Edge y)

 43 {

 44     return x.w < y.w;

 45 }

 46 void init(int n)

 47 {

 48     FOR(i,1,n)pa[i] = i;

 49 }

 50 int findset(int x)

 51 {

 52     return x == pa[x] ? x : pa[x] = findset(pa[x]);

 53 }

 54 int kruskal(int n,int m,int key)

 55 {

 56     init(n);

 57     int ans = 0,cnt=0;

 58     REP(i,m)

 59     {

 60         if(i == key)continue;

 61         int x = findset(edge[i].u),y=findset(edge[i].v);

 62         if(x != y)

 63         {

 64             pa[x] = y;ans += edge[i].w;cnt++;

 65         }

 66         if(cnt == n-1)return ans;

 67     }

 68     return -INF;

 69 }

 70 int main()

 71 {

 72     //freopen("in","r",stdin);

 73     int T;

 74     scanf("%d",&T);

 75     while(T--)

 76     {

 77         int n,m;

 78         scanf("%d%d",&n,&m);

 79         REP(i,m)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);

 80         sort(edge,edge+m,cmp);

 81         int ans = 0,cnt=0;

 82         init(n);

 83         REP(i,m)//最小生成树

 84         {

 85             int x = findset(edge[i].u),y=findset(edge[i].v);

 86             if(x != y)

 87             {

 88                 pa[x] = y;ans += edge[i].w;a[cnt++]=i;

 89             }

 90             if(cnt == n-1)break;

 91         }

 92         REP(i,n-1)

 93         {

 94             int tmp = kruskal(n,m,a[i]);

 95             if(ans == tmp)

 96             {

 97                 ans = -INF;break;

 98             }

 99         }

100         if(ans == -INF)puts("Not Unique!");

101         else printf("%d\n",ans);

102     }

103     return 0;

104 }

 

prim
 1 /*

 2 Author:Zhaofa Fang

 3 Lang:C++

 4 */

 5 #include <cstdio>

 6 #include <cstdlib>

 7 #include <sstream>

 8 #include <iostream>

 9 #include <cmath>

10 #include <cstring>

11 #include <algorithm>

12 #include <string>

13 #include <utility>

14 #include <vector>

15 #include <queue>

16 #include <stack>

17 #include <map>

18 #include <set>

19 using namespace std;

20 

21 typedef long long ll;

22 #define DEBUG(x) cout<< #x << ':' << x << endl

23 #define REP(i,n) for(int i=0;i < (n);i++)

24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)

25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)

26 #define PII pair<int,int>

27 #define PB push_back

28 #define MP make_pair

29 #define ft first

30 #define sd second

31 #define lowbit(x) (x&(-x))

32 #define INF (1<<30)

33 

34 

35 const int maxn = 5050;

36 int maz[maxn][maxn],path[maxn][maxn];

37 bool vist[maxn];

38 int dist[maxn],pre[maxn],Stack[maxn];

39 int n,m;

40 void init(void){

41     FOR(i,1,n)FOR(j,1,n)maz[i][j] = INF, path[i][j] = 0;

42 }

43 int prim(int s){

44     FOR(i,1,n)dist[i] = maz[s][i],vist[i] = 0,pre[i] = s;

45     int top =  0,sum = 0;

46     vist[s] = 1,dist[s] = 0, Stack[top++] = s;

47     while(1){

48         int u = -1;

49         FOR(i,1,n)

50             if(!vist[i] && (u == - 1 || dist[u] > dist[i]))

51                 u = i;

52         if(u == -1)break;

53         sum += dist[u],Stack[top++] =  u,vist[u] = 1;

54         REP(i,top){

55             if(Stack[i] == u)continue;

56             path[Stack[i]][u] = max(path[pre[u]][u],dist[u]);

57             path[u][Stack[i]] = path[Stack[i]][u];

58         }

59         FOR(i,1,n)

60             if(!vist[i] && (maz[u][i]<dist[i]))

61                 dist[i] = maz[u][i],pre[i] = u;

62     }

63     return sum;

64 }

65 void SMT(void){

66     int Min = INF,sum = prim(1);

67     FOR(i,1,n-1)

68         FOR(j,i+1,n)

69             if(pre[i] != j && pre[j] != i && maz[i][j] < INF)

70                 Min = min(Min, sum  - path[i][j] + maz[i][j]);

71     if(Min == sum)puts("Not Unique!");

72     else printf("%d\n",sum);

73 }

74 int main(){

75     //freopen("in","r",stdin);

76     int T;

77     scanf("%d",&T);

78     while(T--){

79         scanf("%d%d",&n,&m);

80         init();

81         int u,v,w;

82         while(m--)

83         {

84             scanf("%d%d%d",&u,&v,&w);

85             maz[u][v] = maz[v][u] = w;

86         }

87         SMT();

88     }

89     return 0;

90 }

 

你可能感兴趣的:(unique)