题目链接: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);
else
printf("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");
else
printf("%d\n",mst);
}
return 0;
}