1. 程式人生 > >次小生成樹

次小生成樹

-m for uniq scan sin class can () ++

 1 /*
 2 最小生成樹唯一嗎,求出次小生成樹
 3 枚舉每個非最小生成樹裏面的邊,
 4 加上該邊後一定會形成環
 5 最小生成樹+該邊-最小生成樹在環中的最長邊
 6 */
 7 /*
 8 #include <cstdio>
 9 #include <iostream>
10 #include <algorithm>
11 #include <cstring>
12 #include <vector>
13 using namespace std;
14 #define ph push_back
15 const int inf =0x3f3f3f3f;
16 const int N =150; 17 #define ph push_back 18 int pre[N],maxx[N][N]; 19 vector<int>ve[N]; 20 int t,n,m; 21 struct Edge{ 22 int from,to,w; 23 bool vis; 24 }e[N*N*2]; 25 bool cmp(Edge a,Edge b){ 26 return a.w<b.w; 27 } 28 int find(int x){ 29 return pre[x] = pre[x]==x?x:find(pre[x]);
30 } 31 void krusal(){ 32 for(int i =0;i<=n;i++){ 33 pre[i]=i; 34 ve[i].clear(); 35 ve[i].ph(i); 36 37 } 38 sort(e,e+m,cmp); 39 int sum=0,cnt=n; 40 for(int i=0;i<m;i++){ 41 if(cnt>1){ 42 int x =find(e[i].from),y=find(e[i].to);
43 if(x!=y){ 44 cnt--; 45 e[i].vis=1; 46 sum+=e[i].w; 47 int l1=ve[x].size(),l2=ve[y].size(); 48 for(int j=0;j<l1;j++){ 49 for(int k =0;k<l2;k++){ 50 maxx[ve[x][j]][ve[y][k]] =maxx[ve[y][k]][ve[x][j]]=e[i].w; 51 //得到任意兩個點之間,在最小生成樹中的最長邊 52 } 53 } 54 pre[x] =y; 55 int temp[N]; 56 for(int j=0;j<l2;j++){ 57 temp[j]=ve[y][j]; 58 } 59 for(int j=0;j<l1;j++){ 60 ve[y].ph(ve[x][j]); 61 } 62 for(int j=0;j<l2;j++){ 63 ve[x].ph(temp[j]); 64 } 65 } 66 } 67 } 68 int minn=inf; 69 for(int i=0;i<m;i++){ 70 if(!e[i].vis){ 71 minn=min(minn,sum+e[i].w-maxx[e[i].from][e[i].to]); 72 73 } 74 } 75 if(minn>sum){ 76 printf("%d\n",sum); 77 } 78 else{ 79 printf("Not Unique!\n"); 80 } 81 } 82 int main() 83 { 84 scanf("%d",&t); 85 while(t--){ 86 scanf("%d%d",&n,&m); 87 for(int i =0;i<m;i++){ 88 scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w); 89 e[i].vis=0; 90 } 91 krusal(); 92 } 93 return 0; 94 } 95 */

次小生成樹