【POJ1697】次小生成树

 

题目链接:http://poj.org/problem?id=1679

题目大意:让你求最小生成树,并判断最小生成树是否唯一。

 

解题思路:本题其实是想让你求次小生成树,如果次小生成树和最小生成树权值和相等,最小生成树则不唯一,否则唯一。

解题步骤:

1、先求最小生成树,求最小生成树过程中标记出现在最小生成树中的边以及fp[i][j],fp数组保存的是最小生成树上从i到j的最大权值。

2、枚举所有未出现在最小生成树中的边map[i][j],找到tp=(map[i][j]-fp[i][j])差值最小的进行替换,为什么可以这样?因为加入map[i][j]到最小生成树中后必形成环,然后消去环中非map[i][j]的最大权值边,得到的解必为最优解。

3、tp==0则最小生成树不唯一,否则唯一。

 

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 #include <queue>

 6 #include <algorithm>

 7 using namespace std;

 8 

 9 const int maxn=110;

10 const int oo=0x3fffffff;

11 int lowcost[maxn], visit[maxn], map[maxn][maxn], used[maxn][maxn], pre[maxn], fp[maxn][maxn]; ///fp数组保存的是最小生成树上从i到j的最大权值边

12 int n, m, T;

13 

14 int Prim()

15 {

16     int sum=0;

17     for(int i=1; i<=n; i++) lowcost[i]=oo, pre[i]=0, visit[i]=0;

18     lowcost[1]=0;

19     for(int i=1; i<=n; i++)

20     {

21         int k=-1, minn=oo;

22         for(int j=1; j<=n; j++)

23             if(minn>lowcost[j]&&!visit[j]) k=j, minn=lowcost[j];

24         if(k==-1) break;

25         if(pre[k]!=0)     ///源点不考虑进去

26         {

27             used[pre[k]][k]=used[k][pre[k]]=2; ///出现在最小生成树中的边标记一下

28             for(int j=1; j<=n; j++)

29                 if(visit[j]) fp[j][k]=max(fp[j][pre[k]],map[pre[k]][k]); ///找生成树中已出现的节点j,求j到k路上最大权值边

30         }

31         visit[k]=1;

32         sum+=lowcost[k];

33         lowcost[k]=0;

34         for(int j=1; j<=n; j++)

35             if(!visit[j]&&lowcost[j]>map[k][j])

36             {

37                 pre[j]=k;

38                 lowcost[j]= map[k][j];

39             }

40     }

41     return sum;

42 }

43 

44 void Solve()

45 {

46     int ans=Prim();

47     int tp=oo;

48     for(int i=1; i<=n; i++)

49         for(int j=1; j<=n; j++)

50            if(used[i][j]==1) tp=min(tp,map[i][j]-fp[i][j]); ///枚举未出现在生成树中的边

51     if(tp==0) puts("Not Unique!");

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

53 }

54 

55 int main()

56 {

57     cin >> T;

58     while(T--)

59     {

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

61         for(int i=1; i<=n; i++)

62             for(int j=1; j<=n; j++) fp[i][j]=used[i][j]=0, map[i][j]=oo;

63         for(int i=0; i<m; i++)

64         {

65             int u, v, val;

66             scanf("%d%d%d",&u,&v,&val);

67             map[u][v]=map[v][u]=val;

68             used[u][v]=used[v][u]=1;

69         }

70         Solve();

71     }

72     return 0;

73 }

 

 

你可能感兴趣的:(poj)