今天又遇到这个题了,我竟然忘记了,真不应该啊。重温一下,把文章从qq空间转过来吧。
说下这题大概思路吧!
1.把有限制的点去掉,剩下的找出各个连通分量,prim最小生成树,就是一片森林。
2.每个连通分量找最短的一条边连到有限制的那点,得到最小m度限制生成树
3.由最小m度限制生成树,得到最小m+1度,m+2度……一直到k度最小限制生成树.
#include <iostream>
#include <string>
using namespace std;
int m,n,ma,mai,p,k,q,zu,u,v,en,tol,ztree=0,maxx=100000003;
string s,t;
bool g[30][30]={0},ff[30];
int a[30][30];
bool b[30][30],vi[30],sf[30];
string ss[30];
int hd[30],fu[30],belong[30],cun1[30],cun2[30],zuida[30],zuii[30];
//zuida保存vi到v0路径上不与v0相连的权值最大的边,zuii表示这条边对应的点,这条边还有另外一个点就是fu[i]了
void prim(int v){ //prim最小生成树,同时找出联通量
int i,j,min,go;
int ans=0;
for (i=0;i<n;i++){
fu[i]=v;
hd[i]=a[v][i];
}
hd[v]=0;
ff[v]=true;
hd[en]=0;
for (i=1;i<n;i++){
min=maxx;
for (j=0;j<n;j++)
if(hd[j]>0&&hd[j]<min){
v=j;
min=hd[j];
}
if (min==maxx) break;
b[(fu[v])][v]=1;
b[v][(fu[v])]=1;
hd[v]=0;
belong[v]=zu;
ff[v]=true;
ztree+=a[fu[v]][v];
for (j=0;j<n;j++)
if(a[v][j]<hd[j]){
fu[j]=v;
hd[j]=a[v][j];
}
}
}
void dfs(int v){ //深度搜索,找出每一次各个节点到park节点的最大的边
int i;
vi[v]=true;
if (v==en||fu[v]==en){
zuida[v]=0;
zuii[v]=v;
sf[v]=false;
}
else {
zuida[v]=zuida[(fu[v])];
zuii[v]=zuii[(fu[v])];
if (zuida[v]<a[fu[v]][v]){
zuida[v]=a[fu[v]][v];
zuii[v]=v;
}
}
for (i=0;i<n;i++)
if (b[v][i]&&!vi[i]){
fu[i]=v;
dfs(i);
}
}
int main(){
int i,j;
bool find;
cin>>m;
n=0;
for (i=0;i<21;i++)
for (j=0;j<21;j++) {
a[i][j]=maxx;
b[i][j]=0;
}
for (i=0;i<m;i++){
cin>>s>>t>>k;
find=false;
for (j=0;j<n;j++){
if (ss[j]==s){ u=j;
find=true;}
}
if (find==false) {
ss[n]=s;
u=n;
if (s=="Park") en=n;
n++;
}
find=false;
for (j=0;j<n;j++){
if (ss[j]==t){ v=j;
find=true;}
}
if (find==false) {
ss[n]=t;
v=n;
if (t=="Park") en=n;
n++;
}
a[u][v]=k;
a[v][u]=k;
g[u][v]=true;
g[v][u]=true;
}
cin>>tol;
for (i=0;i<n;i++){
ff[i]=false;
cun1[i]=maxx;
cun2[i]=maxx;
zuida[i]=maxx;
zuii[i]=maxx;
vi[i]=false;
sf[i]=true;
}
ff[en]=true;
zu=1;
for (i=0;i<n;i++)
if (!ff[i]) {
belong[i]=zu;
prim(i);
zu++;
}
for (i=0;i<n;i++){
if (a[i][en]!=maxx&&cun1[belong[i]]>a[i][en]){
cun1[belong[i]]=a[i][en];
cun2[belong[i]]=i;
}
}
for (i=1;i<zu;i++){
b[cun2[i]][en]=1;
b[en][cun2[i]]=1;
ztree+=a[en][cun2[i]];
}
dfs(en);
for (k=zu;k<=tol;k++){ //最小度的核心代码
ma=maxx;
for (i=0;i<n;i++)
if (g[en][i]&&!b[en][i]&&sf[i]&&(a[en][i]-zuida[i]<ma)){
ma=a[en][i]-zuida[i];
mai=i;
}
if (ma>=0) break;
b[mai][en]=1;
b[en][mai]=1;
u=zuii[mai];
v=fu[u];
b[u][v]=0;
b[v][u]=0;
fu[mai]=en;
sf[mai]=false;
ztree+=ma;
dfs(mai);
}
cout<<"Total miles driven: "<<ztree<<endl;
system("pause");
return 0;
}