1. 程式人生 > >最小生成樹之安慰奶牛

最小生成樹之安慰奶牛

程式碼:有個問題就是陣列開的太大了超出執行的記憶體限制。

#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,但是在尋找的時候還是比較麻煩的)