题目:http://poj.org/problem?id=1639

对根的度数有限制的最小生成树;

先忽略根,跑最小生成树,得到几个连通块,再一一与根连上;

然后在限制内用根连出去的边来使生成树更小,这需要枚举边以及用dp维护树上边的dfs序之前最大的一个;

此题用邻接矩阵比较方便。

改了一晚上,终于发现是混淆了n和cnt,cnt才是点数。

邻接表失败版:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,head[],ct=,cnt,ed,fa[],cost,reg;
char s1[],s2[];
map<string,int>mp;
struct N{
int to,next,w;
N(int t=,int n=,int ww=):to(t),next(n),w(ww) {}
}edge[],e[];
struct NN{
int v,bh;
}dp[];
bool use[],use2[],lk[],vis[];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void kruskal()
{
sort(edge+,edge+ct+,cmp);
for(int i=;i<=n;i++)fa[i]=i;
for(int i=;i<=ct;i+=)
{
int u=edge[i].to;
int v=edge[i^].to;
if(find(u)!=find(v))
{
cost+=edge[i].w;
fa[find(u)]=find(v);
use[i]=;
use[i^]=;
}
}
}
void dfs(int x)
{
vis[x]=;
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(!use[i]||vis[u])continue;
// printf("u=%d\n",u);
// printf("x=%d——u=%d\n",x,u);
if(dp[x].v>edge[i].w)
{
dp[u].v=dp[x].v;
dp[u].bh=dp[x].bh;
}
else
{
// printf("u=%d x=%d\n",u,x);
dp[u].v=edge[i].w;
// printf("dp[%d].v=%d\n",u,dp[u].v);
dp[u].bh=i;
}
dfs(u);
}
}
void add(int x,int y,int z)
{
ct++;
edge[ct].to=y;
edge[ct].next=head[x];
edge[ct].w=z;
head[x]=ct;
}
int main()
{
scanf("%d",&n);
mp["Park"]=++cnt;
for(int i=;i<=n;i++)
{
int x;
scanf("%s %s",&s1,&s2);
scanf("%d",&x);
if(!mp[s1])mp[s1]=++cnt;
if(!mp[s2])mp[s2]=++cnt;
if(mp[s1]==)
{
e[++ed].to=mp[s2];
e[ed].w=x;
continue;
}
if(mp[s2]==)
{
e[++ed].to=mp[s1];
e[ed].w=x;
continue;
}
// edge[++ct]=(mp[s2],head[mp[s1]],x);head[mp[s1]]=ct;
// edge[++ct]=(mp[s1],head[mp[s2]],x);head[mp[s2]]=ct;
add(mp[s2],mp[s1],x);
add(mp[s1],mp[s2],x);
}
// for(int i=2;i<=ct;i++)
// printf("w=%d to=%d\n",edge[i].w,edge[i].to);
scanf("%d",&m);
kruskal();
sort(e+,e+ed+,cmp);
for(int i=;i<=ed;i++)
{
int u=e[i].to;
if(!lk[find(u)])
{
cost+=e[i].w;
lk[find(u)]=;
use2[i]=;
reg++;
}
}
vis[]=;
for(int i=;i<=ed;i++)
{
if(!use2[i])continue;
dp[e[i].to].v=-;
dfs(e[i].to);
}
// for(int i=1;i<=n;i++)
// printf("i=%d v=%d bh=%d\n",i,dp[i].v,dp[i].bh);
// for(int i=1;i<=n;i++)
// printf("dp[%d]=%d\n",i,dp[i].v);
while(reg<m)
{
int mx=-;
int d,k;
for(int i=;i<=ed&&reg<m;i++)
{
if(use2[i])continue;
int u=e[i].to;
if(dp[u].v-e[i].w>mx)
{
mx=dp[u].v-e[i].w;
// cout<<dp[u].v<<" "<<e[i].w<<endl;
d=u;k=i;
}
}
// printf("mx=%d d=%d k=%d\n",mx,d,k);
if(mx<=)break;
cost-=mx;
use[dp[d].bh]=;
use2[k]=;
reg++;
dp[d].v=-;
memset(vis,,sizeof vis);
vis[d]=;
dfs(d);
}
printf("Total miles driven: %d\n",cost);
return ;
}

失败版

代码如下:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int n,m,ct,cnt,fa[],cost,reg,key[],mne[],inf=0x3f3f3f3f;
string s1,s2;
map<string, int>mp;
struct N{
int hd,to,w;
}edge[];
struct NN{
int w,u,v;
}dp[];
bool in[][];
int sid[][];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void kruskal()
{
sort(edge+,edge+ct+,cmp);
// for(int i=1;i<=ct;i++)
// printf("w=%d u=%d v=%d\n",edge[i].w,edge[i].hd,edge[i].to);
for(int i=;i<=cnt;i++)fa[i]=i;//
for(int i=;i<=ct;i++)
{
int u=edge[i].hd;
int v=edge[i].to;
if(u==||v==)continue;
if(find(u)!=find(v))
{
cost+=edge[i].w;
fa[find(u)]=find(v);
in[u][v]=in[v][u]=;
}
}
}
void dfs(int x,int f)
{
for(int u=;u<=cnt;u++)
{
if(!in[x][u]||u==f)continue;
if(dp[u].w==-)
{
if(dp[x].w>sid[x][u])
dp[u]=dp[x];
else
{
dp[u].w=sid[x][u];
dp[u].u=x;dp[u].v=u;
}
}
dfs(u,x);
}
}
int main()
{
scanf("%d",&n);
mp["Park"]=++cnt;
memset(sid,0x3f,sizeof sid);
for(int i=;i<=n;i++)
{
int x;
cin>>s1>>s2>>x;
if(!mp[s1])mp[s1]=++cnt;
if(!mp[s2])mp[s2]=++cnt;
int m1=mp[s1],m2=mp[s2];//!
sid[m1][m2]=sid[m2][m1]=min(sid[m1][m2],x);
edge[++ct].w=x;
edge[ct].hd=m1;edge[ct].to=m2;
}
scanf("%d",&m);
kruskal();
// for(int i=1;i<=cnt;i++)
// for(int j=1;j<=cnt;j++)
// if(in[i][j])printf("in[%d][%d]=%d\n",i,j,in[i][j]);
// cout<<cost<<endl;
memset(mne,0x3f,sizeof mne);
for(int i=;i<=cnt;i++)
{
if(sid[i][]==inf)continue;
int cr=find(i);
if(mne[cr]>sid[i][])
{
mne[cr]=sid[i][];
key[cr]=i;
}
}
for(int i=;i<=cnt;i++)//
{
if(mne[i]==inf)continue;
// cost+=mne[i];
cost+=sid[][key[i]];//
in[][key[i]]=in[key[i]][]=;
reg++;
}
for(int j=reg+;j<=m;j++)
{
memset(dp,-,sizeof dp);
dp[].w=-inf;
for(int i=;i<=cnt;i++)
{
if(in[i][])dp[i].w=-inf;
// else dp[i].w=-1;
}
dfs(,-);
int mn=inf;
int d;
for(int i=;i<=cnt;i++)
{
// if(sid[i][1]==inf)continue;
if(sid[i][]-dp[i].w<mn)
{
mn=sid[i][]-dp[i].w;
d=i;
}
}
if(mn>=)break;
cost+=mn;
in[dp[d].u][dp[d].v]=in[dp[d].v][dp[d].u]=;
in[][d]=in[d][]=;
}
printf("Total miles driven: %d\n",cost);
return ;
}

poj1639顶点度限制生成树的更多相关文章

  1. POJ1639顶点度限制最小生成树

    题目:http://poj.org/problem?id=1639 见汪汀的<最小生成树问题的拓展>. 大体是先忽略与根节点相连的边,做一遍kruscal,得到几个连通块和一个根节点: 然 ...

  2. poj1639 Picnic Planning,K度限制生成树

    题意: 矮人虽小却喜欢乘坐巨大的轿车,车大到能够装下不管多少矮人.某天,N(N≤20)个矮人打算到野外聚餐.为了集中到聚餐地点,矮人A 要么开车到矮人B 家中,留下自己的轿车在矮人B 家,然后乘坐B ...

  3. 【POJ 1639】 Picnic Planning (最小k度限制生成树)

    [题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...

  4. poj 1639 最小k度限制生成树

    题目链接:https://vjudge.net/problem 题意: 给各位看一下题意,算法详解看下面大佬博客吧,写的很好. 参考博客:最小k度限制生成树 - chty - 博客园  https:/ ...

  5. 最小k度限制生成树

    [题目描述] 给你一个图,n个点,m条边,求一颗生成树满足如下条件: (1)结点1的度不超过k. (2)在(1)条件下所求生成树最小. [算法引入] 最小k度限制生成树,就是指有特殊的某一点的度不能超 ...

  6. lesson2-完全图、补图和顶点度

    (一).完全图.偶图与补图 1.每两个不同的顶点之间都有一条边相连的简单图称为完全图 (complete graph).在同构意义下,n个顶点的完全图只有一个,记为 2.所谓具有二分类(X, Y)的偶 ...

  7. Picnic Planning POJ - 1639(度限制生成树)

    解题报告   题意理解 给定一张N个点,M个边的无向图,求出无向图的一颗最小生成树,但是我们要求一号节点的入度不可以超过给定的整数S 也就是一个最小生成树,要求它的一号节点,最多只能和S个节点相连. ...

  8. poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10742   Accepted: 3885 ...

  9. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

随机推荐

  1. ggplot2-为图形加入直线

    本文更新地址:http://blog.csdn.net/tanzuozhev/article/details/51112057 本文在 http://www.cookbook-r.com/Graphs ...

  2. weblogic中部署项目报错org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken .

    原因: 原因是weblogic要查找自己的antlr,和lib下面的antlr包冲突.... 解决方法: 在weblogic.xml添加 <container-descriptor>    ...

  3. python(18)- 协程函数及应用

    协程 def init(func): def wrapper(*args,**kwargs): obj = func(*args,**kwargs) next(obj) return obj retu ...

  4. 重置浏览器的默认样式(css reset)

    (1)定义:首先css reset指的是重置浏览器的默认样式 (2)作用:因为现在的浏览器很多,并且每个浏览器都有自己的默认样式,这样就会导致一个页面在多个浏览器下展示产生差异,所以我们需要做一些处理 ...

  5. Mysql多线程性能测试工具sysbench 安装、使用和测试

    From:http://www.cnblogs.com/zhoujinyi/archive/2013/04/19/3029134.html 摘要:      sysbench是一个开源的.模块化的.跨 ...

  6. POJ 3580(SuperMemo-Splay区间加)[template:Splay V2]

    SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 11384   Accepted: 3572 Case T ...

  7. 横向卷轴(side-scrolling)地图的canvas实现

    标题有点小题大作了,实际上是实现一张看起来连续的运动背景图片. 效果如下:   // 实现原理: 图片1与图片2是两张首尾衔接的图片,图片1以一定速度移出canvas,图片2慢慢移进canvas,当图 ...

  8. unity3d从零開始(五):了解摄像机

    1.简单介绍         Unity的摄像机是用来将游戏世界呈现给玩家的,游戏场景中至少有一台摄像机.也能够有多台. 2.类型         Unity中支持两种类型的摄像机,各自是Perspe ...

  9. MySQL 存储过程 (3)

    以下介绍下像数据库循环插入数据操作 第一步:建立存储过程用到的信息表

  10. EasyIPCamera高性能摄像机RTSP服务器RTSPServer解决方案

    EasyIPCamera EasyIPCamera是由EasyDarwin团队开发的一套非常稳定.易用.支持多种平台(包括Windows/Linux 32&64,Android,ARM his ...