POJ 1679 The Unique MST 次小生成树 裸题
非次小生成树做法:
也可以标记最小生成树的边
然后删边 看sum值是否等与最小值
注意 删边可能变成森林
但是耗时较多:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int maxn =1000+5; const int maxe = 15000+5; int father[maxn],n,m; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void merge(int a,int b) { int fx,fy; fx=find(a); fy=find(b); if(fx!=fy) father[fx]=fy; } struct node { int from,to,val; bool select; } edge[maxe]; bool cmp(node a,node b) { if(a.val!=b.val) return a.val<b.val; if(a.from!=b.from) return a.from<b.from; return a.to<b.to; } int kruskal(int t) { int k=0; int i,x,y; int ans=0; for(i=1; i<=n; i++) { father[i]=i; } sort(edge,edge+m,cmp); for(i=0; i<m; i++) { if(k==n-1) break; if(edge[i].val<0) continue; if(i==t) continue; x=find(edge[i].from); y=find(edge[i].to); if(x!=y) { merge(x,y); k++; ans+=edge[i].val; if(t==-1) edge[i].select=true; } } return ans; } void init() { memset(edge,0,sizeof(edge)); } int main() { // freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=0; i<m; i++) { scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val); } int ans=kruskal(-1); int flag=0; for(int i=0; i<m; i++) { if(edge[i].select)// { int num=0,a=kruskal(i); for(int j=1; j<=n; j++) { if(father[j]==j) num++; } if(num>1) continue; if(ans==a) flag=1; } } if(flag) { printf("Not Unique!\n"); } else printf("%d\n",ans); } return 0; }
次小生成树:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int maxn =1000+5; const int maxe = 15000+5; int father[maxn],n,m; int length[maxn][maxn],head[maxn],end[maxn]; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void merge(int a,int b) { int fx,fy; fx=find(a); fy=find(b); if(fx!=fy) father[fx]=fy; } struct node { int from,to,val; bool select; } edge[maxe]; struct node1 { int to,next; }link[maxn]; bool cmp(node a,node b) { if(a.val!=b.val) return a.val<b.val; if(a.from!=b.from) return a.from<b.from; return a.to<b.to; } int maxx; void kruskal(int t) { for(int i=0;i<=n;i++) { link[i].to=i+1; link[i].next=head[i+1]; end[i+1]=i; head[i+1]=i; } int k=0; int x,y; int ans=0; for(int i=1; i<=n; i++) { father[i]=i; } sort(edge,edge+m,cmp); for(int i=0; i<m; i++) { if(k==n-1) break; if(edge[i].val<0) continue; // if(i==t) continue; x=find(edge[i].from); y=find(edge[i].to); if(x!=y) { for(int j=head[x]; j!=-1; j=link[j].next) { for(int k=head[y]; k!=-1; k=link[k].next) { length[link[j].to][link[k].to]=length[link[k].to][link[j].to]=edge[i].val; } } link[end[y]].next=head[x]; end[y]=end[x]; merge(x,y); k++; edge[i].select=true; } } } void init() { memset(edge,0,sizeof(edge)); memset(head,-1,sizeof(head)); } int main() { // freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=0; i<m; i++) { scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val); // // edge[i+m]=edge[i]; // edge[i+m].from=edge[i].to; // edge[i+m].to=edge[i].from; } kruskal(1); int mst=0; for(int i=0;i<m;i++) { if(edge[i].select) mst+=edge[i].val; } int secmst=INT_MAX; for(int i=0;i<m;i++) { if(!edge[i].select) secmst=min(secmst,mst+edge[i].val-length[edge[i].from][edge[i].to]); } if(secmst==mst) { printf("Not Unique!\n"); } else printf("%d\n",mst); } return 0; }