poj 1679 《次小生成树的两种求法》

来源:互联网 发布:淘宝不支持花呗 编辑:程序博客网 时间:2024/05/30 07:14

题目链接:poj 1679

两种方法的时间复杂度不同--

第一种好写--第二种时间复杂度小--

当m*n>>n*n时,为避免超时请用第二种


第一种以前写的:

时间复杂度为O(n*m);

思路是:先求出最小生产树--然后依次屏蔽一条边--重新求最小生成树...

每次时间需要m,一共求n次

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct nood{int aa,bb,cc;}bian[60000];int fer[120];int find(int xx){while (fer[xx]==xx)return xx;return fer[xx]=find(fer[xx]);}bool cmp(nood xx,nood yy){return xx.cc<yy.cc;} int n,m;int ks(int ii){for (int i=1;i<=n;i++)fer[i]=i;int ss=0,nn=1;for (int i=0;i<m;i++){if (i==ii) continue;else if (find(bian[i].aa)!=find(bian[i].bb)){nn++;ss+=bian[i].cc;fer[find(bian[i].aa)]=find(bian[i].bb);}}if (nn!=n)ss=-1;return ss;}int main(){int t;scanf("%d",&t);while (t--){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)fer[i]=i;for (int i=0;i<m;i++)scanf("%d%d%d",&bian[i].aa,&bian[i].bb,&bian[i].cc);sort(bian,bian+m,cmp);int s=0;bool shu[12000];for (int i=0;i<m;i++)shu[i]=true;for (int i=0;i<m;i++)if (find(bian[i].aa)!=find(bian[i].bb)){shu[i]=false;s+=bian[i].cc;fer[find(bian[i].aa)]=find(bian[i].bb);}bool falg=true; for (int i=0;i<m;i++){if (shu[i]) continue;int p=ks(i);if (p==s){falg=false;break;}}if (falg)printf("%d\n",s);elseprintf("Not Unique!\n");}return 0;}



第二种方法:

求最小生成树时再用邻接表记录最小生成树中任意两点间的最长路---

然后加边删点---

时间复杂度为O(n*n);

时间大部分在更新两点间的最长路--

代码:

#include<cstdio> #include<cstring>#include<algorithm>using namespace std;struct node{int a,b;int w;bool select;}edges[10020];bool cmp(node xx,node yy){if (xx.w!=yy.w)return xx.w<yy.w;if (xx.a!=yy.a)return xx.a<yy.a;return xx.b<yy.b;}struct node1{int to;int next; }link[10020];int n,m,il;int head[120],end[120];int length[120][120];int fer[120];int find(int xx){if (xx==fer[xx])return xx;return fer[xx]=find(fer[xx]);}void kruskal(node * edges,int n,int m){int k=0;for (il=1;il<=n;il++){link[il].to=il;link[il].next=head[il];end[il]=il;head[il]=il;}sort(edges,edges+m,cmp);for (int i=0;i<m;i++){if (k==n-1) break;int x=find(edges[i].a);int y=find(edges[i].b);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]=edges[i].w;}link[end[y]].next=head[x];end[y]=end[x];fer[x]=y;k++;edges[i].select=true;}}}int main(){int t;scanf("%d",&t);while (t--){scanf("%d%d",&n,&m);int x,y,z;for (int i=0;i<=n;i++)  {head[i]=-1;fer[i]=i;}for (int i=0;i<m;i++){scanf("%d%d%d",&x,&y,&z);edges[i].a=x;edges[i].b=y;edges[i].w=z;edges[i].select=false;}int mst,mmst;kruskal(edges,n,m);mst=0;for (int i=0;i<m;i++)if (edges[i].select)mst+=edges[i].w;mmst=99999999;for (int i=0;i<m;i++)if (!edges[i].select)mmst=min(mst+edges[i].w-length[edges[i].a][edges[i].b],mmst);//printf("%d   %d\n",mst,mmst);if (mst==mmst)printf("Not Unique!\n");elseprintf("%d\n",mst);}return 0;}




0 0
原创粉丝点击