每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水。

  打井和接水两种的付出代价都接边。设一个超级源点,每家每户打井的代价就是从该点(0)到该户人家(1~n)的边的权值。接水有两种可能,从高处接水,那么代价是哈密顿距离与Y的乘积(可以认为就是水管的费用);从低处接水,还要加上付出水泵的钱(水管+水泵的费用)。这样就可以建图了。图论,会建图的话问题就解决一半了。

  然后,用模版来解题。不过朱刘算法的模版时间复杂度的差异还是蛮大的。我的模版的建图是邻接矩阵,时间复杂度是O(N^3)。超时,过不了。在网上找了一份按前向星(边的起点、终点、权值)建图的模版。AC了。该算法的复杂度是O(M)。

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = , M=,INF=0x3f3f3f3f;
int pre[N],id[N],in[N],vis[N];
int tot;//边数
struct node
{
int u,v,w;
}e[M];
void adde(int i,int j,int k)
{
e[tot].u=i;e[tot].v=j;e[tot++].w=k;
}
int zhuliu(int root ,int vn)
{
int ans=;
int cnt;
while()
{
for(int i=;i<vn;i++)
in[i]=INF,id[i]=-,vis[i]=-;
for(int i=;i<tot;i++)
{
if(in[e[i].v]>e[i].w && e[i].u!=e[i].v)
{
pre[e[i].v]=e[i].u;
in[e[i].v]=e[i].w;
}
}
in[root]=;
pre[root]=root;
for(int i=;i<vn;i++)
{
ans+=in[i];
if(in[i]==INF)//这一步可以看出是否存在这样一棵树形图,因此可以略去DFS
return -;
}
cnt=;
for(int i=;i<vn;i++)
{
if(vis[i]==-)
{
int t=i;
while(vis[t]==-)
{
vis[t]=i;
t=pre[t];
}
if(vis[t]!=i || t==root) continue;
for(int j=pre[t];j!=t;j=pre[j])
id[j]=cnt;
id[t]=cnt++;
}
}
if(cnt==) break;
for(int i=;i<vn;i++)
if(id[i]==-)
id[i]=cnt++;
for(int i=;i<tot;i++)
{
int u,v;
u=e[i].u;
v=e[i].v;
e[i].u=id[u];
e[i].v=id[v];
e[i].w-=in[v];
}
vn=cnt;
root=id[root];
}
return ans;
} struct Node
{
int a,b,c;
}nd[N];
int main()
{
//freopen("test.txt","r",stdin);
int n,x,y,z,i,j,k,d;
while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
{
if(!n) break;
tot=;
for(i=;i<=n;i++)
{
scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
adde(,i,nd[i].c*x);
}
for(i=;i<=n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&j);
if(i==j) continue;
d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
d*=y;
if(nd[i].c<nd[j].c) d+=z;
adde(i,j,d);
}
}
int ans=zhuliu(,n+);
if(ans==-) printf("poor XiaoA\n");
else printf("%d\n",ans);
}
return ;
}

下面是邻接矩阵建图的模版,虽然超时了。但是模版还是有借鉴意义的。模版来自哈工大出版的《图论及应用》。

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = , INF=0x3f3f3f3f;
int Map[N][N];
bool vis[N],f[N];
//f是缩点标记,1表示该点已经被缩掉
int pre[N];
int zhuliu(int n)
{
int sum=;
int i,j,k;
for(i=;i<n;i++)
{
f[i]=;
Map[i][i]=INF;
}
pre[]=;
while()
{
//求最短弧集合E0
for(i=;i<n;i++)
{
if(f[i]) continue;
pre[i]=i;
for(j=;j<n;j++)
if(!f[j]&&Map[j][i]<Map[pre[i]][i]) pre[i]=j;
if(pre[i]==i) return -; //没有入边,不存在最小树形图
}
//检查E0
for(i=;i<n;i++)
{
if(f[i]) continue ;
//从当前点开始找环
for(j=;j<n;j++) vis[j]=;
vis[]=;
j=i;
do
{
vis[j]=;
j=pre[j];
}
while(!vis[j]) ;
if(!j) continue; //没有找到环
//收缩G中的有向环
i=j;
//将整个环的权值保存,累计入原图的最小树形图
do
{
sum+=Map[pre[j]][j];
j=pre[j];
}
while(j!=i) ;
j=i;
//对与环上的点有关的边,修改边权
do
{
for(k=; k<n; k++)
if(!f[k]&&Map[k][j]<INF&&k!=pre[j])
Map[k][j]-= Map[pre[j]][j];
j=pre[j];
}
while(j!=i) ;
//缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i
for(j=;j<n;j++)
{
if(j==i) continue;
for(k=pre[i]; k!=i; k=pre[k])
{
if(Map[k][j]<Map[i][j]) Map[i][j] =Map[k][j];
if(Map[j][k]<Map[j][i]) Map[j][i] =Map[j][k];
}
}
//标记环上其他的点为被缩掉
for(j=pre[i];j!=i;j=pre[j]) f[j] =;
//当前环缩点结束,形成新的图G’,跳出继续求G’的最小树形图
break;
}
//如果所有的点都被检查且没有环存在,现在的最短弧集合E0就是
//最小树形图,累计如sum, 算法结束
if(i==n)
{
for(i=;i<n;i++) if(!f[i]) sum+=Map[pre[i]][i];
break;
}
}
return sum;
} struct node
{
int a,b,c;
}nd[N];
int main()
{
//freopen("test.txt","r",stdin);
int n,x,y,z,i,j,k,d;
while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
{
if(!n) break;
for(i=;i<=n;i++)
for(j=;j<i;j++)
Map[j][i]=Map[i][j]=INF;
for(i=;i<=n;i++)
{
scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
Map[][i]=nd[i].c*x;
}
for(i=;i<=n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&j);
if(i==j) continue;
d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
d*=y;
if(nd[i].c>=nd[j].c) d+=z;
Map[i][j]=min(d,Map[i][j]);
}
}
printf("%d\n",zhuliu(n+));
}
return ;
}

hdu4009 Transfer water 最小树形图的更多相关文章

  1. HDU4009 Transfer water —— 最小树形图 + 不定根 + 超级点

    题目链接:https://vjudge.net/problem/HDU-4009 Transfer water Time Limit: 5000/3000 MS (Java/Others)    Me ...

  2. HDU 4009 Transfer water 最小树形图

    分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...

  3. HDOJ 4009 Transfer water 最小树形图

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  4. HDU4009 Transfer water 【最小树形图】

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  5. POJ 3164 Command Network 最小树形图模板

    最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...

  6. HDU 4009——Transfer water——————【最小树形图、不定根】

    Transfer water Time Limit:3000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64u Subm ...

  7. HDU 4009 Transfer water(最小树形图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...

  8. 最小树形图(hdu4009)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  9. HDU4009:Transfer water(有向图的最小生成树)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)To ...

随机推荐

  1. Windows上架设自己的ssh代理 — copSSH

    最近网上对ssh代理讨论的比较多, 主要是为了穿墙. 其实在自己的电脑上也可以架设ssh代理, 当然国内自己架的不具有FQ功能, 如果你有国外朋友或是远程win服务器…则可以用此方法架设私有代理. 其 ...

  2. socket主要函数介绍

    1.   基本套接字函数(1)socket函数原型 socket(建立一个socket文件描述符) 所需头文件 #include <sys/types.h> #include <sy ...

  3. eas之单据转换规则

    /**  * BOTP单据转换  * @param botpNum 转换规则编号  * @param BillInfo 原单据  */ public static void BOTP(String b ...

  4. 一键安装LNMP(适合centos7)

    1.准备工作,下载源码包 wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.22-linux-glibc2.12-x86_64.tar ...

  5. C++ 类型转化(运算符重载函数)和基本运算符重载(自增自减)

    类型转化(运算符重载函数) 用转换构造函数可以将一个指定类型的数据转换为类的对象.但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成double类型数据).在C ...

  6. 搜索引擎seo优化

    <a href="" title="SEO优化"></a> <img src="" alt="SEO ...

  7. centos 7.2 安装php56-xml

    linux下, 使用thinkphp的模板标签,如 eq, gt, volist defined, present , empty等 标签时, 报错: used undefined function ...

  8. (24)Spring Boot环境变量读取和属性对象的绑定【从零开始学Spring Boot】

    凡是被Spring管理的类,实现接口 EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到系统环境变量和application配置文件中的变量. com. ...

  9. 【ACM】hdu_1042_N!_201308071639

    N!Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...

  10. [bzoj2124]等差子序列_线段树_hash

    等差子序列 bzoj-2124 题目大意:给定一个1~n的排列,问是否存在3个及以上的位置上的数构成连续的等差子序列. 注释:$1\le n\le 10^4$. 想法:这题就相当于是否存在3个数i,j ...