hdu4009 Transfer water 最小树形图
每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水。
打井和接水两种的付出代价都接边。设一个超级源点,每家每户打井的代价就是从该点(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 最小树形图的更多相关文章
- HDU4009 Transfer water —— 最小树形图 + 不定根 + 超级点
题目链接:https://vjudge.net/problem/HDU-4009 Transfer water Time Limit: 5000/3000 MS (Java/Others) Me ...
- HDU 4009 Transfer water 最小树形图
分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...
- HDOJ 4009 Transfer water 最小树形图
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- HDU4009 Transfer water 【最小树形图】
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- POJ 3164 Command Network 最小树形图模板
最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...
- HDU 4009——Transfer water——————【最小树形图、不定根】
Transfer water Time Limit:3000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64u Subm ...
- HDU 4009 Transfer water(最小树形图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...
- 最小树形图(hdu4009)
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- HDU4009:Transfer water(有向图的最小生成树)
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)To ...
随机推荐
- 触发a标签
var aLink = document.createElement("a"); aLink.download = ''; aLink.href = url; if (docume ...
- RBM(受限玻尔兹曼机)和深层信念网络(Deep Brief Network)
目录: 一.RBM 二.Deep Brief Network 三.Deep Autoencoder 一.RBM 1.定义[无监督学习] RBM记住三个要诀:1)两层结构图,可视层和隐藏层:[没输出层] ...
- 3..jquery的ajax获取form表单数据
jq是对dom进行的再次封装.是一个js库,极大简化了js使用 jquery库在js文件中,包含了所有jquery函数,引用:<script src="jquery-1.11.1.mi ...
- CentOS 7 x64下Apache+MySQL(Mariadb)+PHP5.6的安装
每次搭建新服务器,都要来来回回把这些包再装一下,来来回回搞了不下20遍了吧,原来都是凭经验,配置过程中重复入坑是难免的,故写此文做个备忘.虽然有像xampp这样的集成包,但是在生产环境的Linux发行 ...
- 把 Python 脚本打包成可以直接双击运行的 .exe 文件 【转】
因为最近要用到 Python 脚本,所以自己学习了一下,顺便学习如何把它打包成 .exe 可执行文件,达到双击运行的效果,网上找了资料,保存下来学习用,原文出处:https://baijiahao.b ...
- [bzoj1084][SCOI2005]最大子矩阵_动态规划_伪·轮廓线dp
最大子矩阵 bzoj-1084 SCOI-2005 题目大意:给定一个n*m的矩阵,请你选出k个互不重叠的子矩阵使得它们的权值和最大. 注释:$1\le n \le 100$,$1\le m\le 2 ...
- 实现icon和文字垂直居中的两种方法-(vertical-align and line-height)
方法一:vertical-align 在w3school定义:该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐 百思不得骑姐 然后Google,反正在w3schools上面并没有找到定义 仅 ...
- S 禁止F12和右键操作控制台,兼容各浏览器
document.oncontextmenu = function () { return false; }; document.onkeydown = function () { ...
- A. Music(Codeforces Round #315 (Div. 2) 求最大的容纳量)
A. Music time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- SQL SEVER 元年是1900年
用SQL语句求 本月第一天,怎么写? 可以这样写: SELECT DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0); 按照日期函数DATEDIFF的定义,第二个参数是开始日 ...