最小生成树之安慰奶牛

来源:互联网 发布:编写sql语句的工具 编辑:程序博客网 时间:2024/05/23 01:58

代码:有个问题就是数组开的太大了超出运行的内存限制。

#include<iostream>

#include<string.h>
#include<algorithm>
using namespace std;
int cost[10005];
#define MIN 0x7fffffff
typedef struct
{
int connect[10005][10005];
int n;
}Mat;
Mat g;
int prim(int start)
{
int lowcost[10005],m,record,closest[10005];
for(int i=1;i<=g.n;i++)
{
lowcost[i]=g.connect[start][i];
closest[i]=start;
}
for(int j=2;j<=g.n;j++)//找出n-1个点 
{
m=MIN;
for(int k=1;k<=g.n;k++)
{
if(lowcost[k]!=0&&lowcost[k]!=-1&&lowcost[k]<m)
{
m=lowcost[k];
record=k;
}
}
cout<<"当前选择点为:"<<record<<endl;
lowcost[record]=0;
for(int u=1;u<=g.n;u++)
{
if(lowcost[u]&&g.connect[record][u]!=0&&(lowcost[u]==-1||lowcost[u]>g.connect[record][u]&&g.connect[record][u]!=-1))
{
cout<<"原值为"<<lowcost[u]<<"  "<<"现值为"<<g.connect[record][u]<<endl; 
lowcost[u]=g.connect[record][u];
closest[u]=record;//记录前驱 
}
}
}
int sum1=0;
for(int y=1;y<=g.n;y++)
{
int s1=closest[y];
int o1=y;
sum1+=g.connect[s1][o1];

return sum1;
}


int main()
{
int n,p,max1=0x80000000,record,data=0x7fffffff;
cin>>n>>p;
for(int t=1;t<=n;t++)
{
cin>>cost[t];
if(cost[t]<data)
{
data=cost[t];
record=t;
}
}
memset(g.connect,-1,sizeof(g.connect));
for(int z=1;z<=p;z++)
{
int s,e,c;
cin>>s>>e>>c;
if(max1<max(s,e))
{
max1=max(s,e);
}
if(g.connect[s][e]==-1||g.connect[e][s]==-1)
{
g.connect[s][e]=g.connect[e][s]=2*c+cost[e]+cost[s];
}
else
{
g.connect[e][s]=g.connect[s][e]=min(2*c+cost[e]+cost[s],g.connect[s][e]);
}
}
for(int l=1;l<=max1;l++)
{
g.connect[l][l]=0;
}
g.n=max1;
cout<<"图表为:"<<endl;
for(int q=1;q<=max1;q++)
{
for(int f=1;f<=max1;f++)
{
cout<<g.connect[q][f]<<"  ";
}
cout<<endl;
}
cout<<"\n\n\n";

cout<<prim(1)+cost[record];
return 0;

}

优化1:vector动态偷空间,因为静态数组是无法更改大小的,所以必须在声明的时候开的足够大,这样可能连基本样例都运行不了,因此用vector动态开一个二维数组即可。

include<iostream>
#include<string.h>
#include<algorithm>
#include<vector> 
using namespace std;
int cost[10005];
#define MIN 0x7fffffff
typedef struct
{
vector<vector<int> > connect;
int n;
}Mat;




Mat g;




int prim(int start)
{
int lowcost[10005],m,record,closest[10005];
for(int i=1;i<=g.n;i++)
{
lowcost[i]=g.connect[start][i];
closest[i]=start;
}
for(int j=2;j<=g.n;j++)//找出n-1个点 
{
m=MIN;
for(int k=1;k<=g.n;k++)
{
if(lowcost[k]!=0&&lowcost[k]!=-1&&lowcost[k]<m)
{
m=lowcost[k];
record=k;
}
}
cout<<"当前选择点为:"<<record<<endl;
lowcost[record]=0;
for(int u=1;u<=g.n;u++)
{
if(lowcost[u]&&g.connect[record][u]!=0&&(lowcost[u]==-1||lowcost[u]>g.connect[record][u]&&g.connect[record][u]!=-1))
{
cout<<"原值为"<<lowcost[u]<<"  "<<"现值为"<<g.connect[record][u]<<endl; 
lowcost[u]=g.connect[record][u];
closest[u]=record;//记录前驱 
}
}
}
int sum1=0;
for(int y=1;y<=g.n;y++)
{
int s1=closest[y];
int o1=y;
sum1+=g.connect[s1][o1];

return sum1;
}


int main()
{
int n,p,max1=0x80000000,record,data=0x7fffffff;
cin>>n>>p;
for(int b=0;b<=n;b++)
{
vector<int> v(n+1,-1); 
g.connect.push_back(v);
}
for(int t=1;t<=n;t++)
{
cin>>cost[t];
if(cost[t]<data)
{
data=cost[t];
record=t;
}
}
for(int z=1;z<=p;z++)
{
int s,e,c;
cin>>s>>e>>c;
if(max1<max(s,e))
{
max1=max(s,e);
}
if(g.connect[s][e]==-1||g.connect[e][s]==-1)
{
g.connect[s][e]=g.connect[e][s]=2*c+cost[e]+cost[s];
}
else
{
g.connect[e][s]=g.connect[s][e]=min(2*c+cost[e]+cost[s],g.connect[s][e]);
}
}
for(int l=1;l<=max1;l++)
{
g.connect[l][l]=0;
}
g.n=max1;
cout<<"图表为:"<<endl;
for(int q=1;q<=max1;q++)
{
for(int f=1;f<=max1;f++)
{
cout<<g.connect[q][f]<<"  ";
}
cout<<endl;
}
cout<<"\n\n\n";
cout<<prim(1)+cost[record];
return 0;
}

初步测试可以偷到一半的分,好了,继续优化。

优化2:因为这种存图的矩阵实际上是对称的,所以connect[s][j]==connect[j][s],所以我们只需要规定s>=j也就是下三角矩阵部分就行,对于这个部分,完全可以采用一维存储。存储公式为connect[s][j]==data[(s-1)*s/2+j]

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int cost[10005];
#define MIN 0x7fffffff
typedef struct
{
int connect[26000000];
int n;
}Mat;




Mat g;




int prim(int start)
{
int lowcost[10005],m,record,closest[10005];
for(int i=1;i<=g.n;i++)
{
int s1=max(start,i);
int e1=min(start,i);
int tran=(s1-1)*s1/2+e1;
lowcost[i]=g.connect[tran];
closest[i]=start;
}
for(int j=2;j<=g.n;j++)//找出n-1个点 
{
m=MIN;
for(int k=1;k<=g.n;k++)
{
if(lowcost[k]!=0&&lowcost[k]!=-1&&lowcost[k]<m)
{
m=lowcost[k];
record=k;
}
}
lowcost[record]=0;
for(int u=1;u<=g.n;u++)
{
int s1=max(record,u);
int e1=min(record,u);
int tran=(s1-1)*s1/2+e1;
if(lowcost[u]&&g.connect[tran]!=0&&(lowcost[u]==-1||lowcost[u]>g.connect[tran]&&g.connect[tran]!=-1))
{
lowcost[u]=g.connect[tran];
closest[u]=record;//记录前驱 
}
}
}
int sum1=0;
for(int y=1;y<=g.n;y++)
{
int s1=max(closest[y],y);
int o1=min(closest[y],y);
sum1+=g.connect[s1*(s1-1)/2+o1];

return sum1;
}


int main()
{
int n,p,max1=0x80000000,record,data=0x7fffffff;
cin>>n>>p;
for(int t=1;t<=n;t++)
{
cin>>cost[t];
if(cost[t]<data)
{
data=cost[t];
record=t;
}
}
memset(g.connect,-1,sizeof(g.connect));
for(int z=1;z<=p;z++)
{
int s,e,c;
cin>>s>>e>>c;
if(max1<max(s,e))//(s为行 e为列)
{
max1=max(s,e);
}
int s1=max(s,e);
int e1=min(s,e);
int tran=(s1-1)*s1/2+e1;
if(g.connect[tran]==-1)
{
g.connect[tran]=2*c+cost[e1]+cost[s1];
}
else
{
g.connect[tran]=min(2*c+cost[e1]+cost[s1],g.connect[tran]);
}
}
for(int l=1;l<=max1;l++)
{
g.connect[l*(l-1)/2+l]=0;
}
g.n=max1;
cout<<prim(1)+cost[record];
return 0;
}


优化3:三元组(即定义一个结构体node,含有成员row,col,value,但是在寻找的时候还是比较麻烦的)