您的位置:首页 > 其它

poj 1639 Picnic Planning 最小k度生成树

2016-03-08 23:26 435 查看
题目:点击打开链接

题意:

就是求最小限度生成树,不会做,我是参考这篇http://www.cnblogs.com/jackge/archive/2013/05/12/3073669.html博客做的

分析:

要求最小 k 度生成树,我们可以按照下面的步骤来做:

设有度限制的点为 V0 ,V0称为根节点

1,把所有与 V0 相连的边删去,图会分成多个子图(假设为 m 个,显然的,如果 m > k,那么问题无解),让他们分别求最小生成树;然后用最小的代价将 m 个最小生成树和 V0 连起来,那我们就得到了一棵关于 V0 的最小 m 度生成树。

2,在 m 度生成树中找一个点和 V0 相连(设这条边的权值为 a),会生成一个环,为了满足最小生成树的要求,我们必须删掉一条边(设这条边的权值为 b),以使总权值尽量小,那么就要求 a 尽量的小,b 尽量的大。

完成一次 2 的操作后得到的是 m+1 度最小生成树,以此类推,直到得到最小 k 度生成树。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=30;
struct node
{
int v,cap;
node(){}
node(int v,int cap):v(v),cap(cap){}
bool operator <(const node &a)const{
return a.cap<cap;
}
};
map<string,int>mp;
int g

,dis
,col
,pre
,fst
,maxside
;
int n,m,k;
int Prim(int src,int id)
{
priority_queue<node>q;
while(!q.empty())q.pop();
dis[src]=0;
q.push(node(src,0));
int ans=0;
while(!q.empty()){
node cur=q.top();
q.pop();
int u=cur.v;
if(!col[u]){
col[u]=id;
ans+=dis[u];
for(int i=1;i<n;i++){
if(!col[i]&&g[u][i]!=0&&dis[i]>g[u][i]){
pre[i]=u;
dis[i]=g[u][i];
q.push(node(i,dis[i]));
}
}
}
}
return ans;

}
void update(int cur,int last,int max_side)
{
maxside[cur]=max_side>g[cur][last]?max_side:g[cur][last];
for(int i=1;i<n;i++)
if(i!=last&&g[cur][i]!=0&&(pre[cur]==i||pre[i]==cur))
update(i,cur,maxside[cur]);
}
void test2()
{
cout<<endl;
for(int i=0;i<n;i++)cout<<maxside[i]<<' ';
cout<<endl;
}
void solve()
{
for(int i=0;i<n;i++){
dis[i]=INF;
col[i]=pre[i]=fst[i]=0;
}
int res=0,cnt=1;
for(int i=1;i<n;i++)
if(!col[i])res+=Prim(i,cnt++);
// update(2,0,0);
//test2();
for(int i=1;i<n;i++){
int id=col[i];
if(g[0][i]!=0&&(!fst[id]||g[0][i]<g[0][fst[id]]))fst[id]=i;
}
//cout<<fst[1]<<endl;
for(int i=1;i<cnt;i++){
res+=g[0][fst[i]];
g[0][fst[i]]=g[fst[i]][0]=0;
update(fst[i],0,0);
}
// test2();
k=k-cnt+1;
while(k--){
int tmp=0;
for(int i=1;i<n;i++){
if(g[0][i]!=0&&(tmp==0||maxside[tmp]-g[0][tmp]<maxside[i]-g[0][i]))
tmp=i;
}
if(maxside[tmp]<=g[0][tmp])break;
res=res-maxside[tmp]+g[0][tmp];
g[0][tmp]=g[tmp][0]=0;
int p=0;
for(int i=tmp;pre[i]!=0;i=pre[i]){
if(p==0||g[p][pre[p]]<g[i][pre[i]])p=i;
}
pre[p]=0;
update(tmp,0,0);
// test2();
}
printf("Total miles driven: %d\n",res);
}
int main()
{
// freopen("f.txt","r",stdin);
char s1[20],s2[20];
int cap;
while(~scanf("%d",&m)){
mp["Park"]=0;
memset(g,0,sizeof(g));
n=1;
while(m--){
scanf("%s%s%d",s1,s2,&cap);
if(!mp.count(s1))mp[s1]=n++;
if(!mp.count(s2))mp[s2]=n++;
int u=mp[s1],v=mp[s2];
if(!g[u][v]||g[u][v]>cap)g[u][v]=g[v][u]=cap;
}
scanf("%d",&k);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: