题目: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. SD卡操作相关的工具SDCardUtils

    SD卡操作相关的工具 package com.flyou.utils; import java.io.File; import android.os.Environment; import andro ...

  2. Html5学习笔记1 元素 标签 属性

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. mysql: 关于MySQL InnoDB锁行还是锁表?

          baidu zone - 关于MYSQL Innodb 锁行还是锁表,深入讲解

  4. Android添加系统级顶层窗口 和 WindowManager添加view的动画问题

    当Dialog有编辑框时如果选择会弹菜单窗口就不要用 Context applicationContext = mainActivity.getApplicationContext(); AlertD ...

  5. Apcahe Shiro学习笔记(二):通过JDBC进行权限控制

    一.概述: 官方对Realm(领域)的描述:https://www.infoq.com/articles/apache-shiro 其功能本质上是一个安全特定的DAO,用于链接数据持久层(任何形式的都 ...

  6. bootstrap-table自己配置

    function initTable(){ var methodNameSearch=$("#methodNameSearch").val(); var requestUrl =  ...

  7. erlang启动参数记录

    不管在erlang的shell下还是脚本里,启动参数都是非常有用的,抽空儿整理下erlang的常用启动参数: +A size   异步线程池的线程数,范围为0~1024,默认为10 +P Number ...

  8. 网络摄像机IPCamera RTSP直播播放网络/权限/音视频数据/花屏问题检测与分析助手EasyRTSPClient

    前言 最近在项目中遇到一个奇怪的问题,同样的SDK调用,访问海康摄像机的RTSP流,发保活OPTIONS命令保活,一个正常,而另一个一发就会被IPC断开,先看现场截图: 图1:发OPTIONS,摄像机 ...

  9. bootstrap-table 行内编辑

    1.文件引入 <link rel="stylesheet" href="bootstrap.css"> <link rel="sty ...

  10. 修改JDK环境变量,不生效的问题

    一般是在/etc/profile下面配置JDK的环境变量 JAVA_HOME=/data/jdk1.7.0_72 JRE_HOME=/data/jdk1.7.0_72/jre PATH=$PATH:$ ...