hdu4009 Transfer water 最小树形图
每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水。
打井和接水两种的付出代价都接边。设一个超级源点,每家每户打井的代价就是从该点(0)到该户人家(1~n)的边的权值。接水有两种可能,从高处接水,那么代价是哈密顿距离与Y的乘积(可以认为就是水管的费用);从低处接水,还要加上付出水泵的钱(水管+水泵的费用)。这样就可以建图了。图论,会建图的话问题就解决一半了。
然后,用模版来解题。不过朱刘算法的模版时间复杂度的差异还是蛮大的。我的模版的建图是邻接矩阵,时间复杂度是O(N^3)。超时,过不了。在网上找了一份按前向星(边的起点、终点、权值)建图的模版。AC了。该算法的复杂度是O(M)。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int N = 1010, M=1010000,INF=0x3f3f3f3f; 6 int pre[N],id[N],in[N],vis[N]; 7 int tot;//边数 8 struct node 9 { 10 int u,v,w; 11 }e[M]; 12 void adde(int i,int j,int k) 13 { 14 e[tot].u=i;e[tot].v=j;e[tot++].w=k; 15 } 16 int zhuliu(int root ,int vn) 17 { 18 int ans=0; 19 int cnt; 20 while(1) 21 { 22 for(int i=0;i<vn;i++) 23 in[i]=INF,id[i]=-1,vis[i]=-1; 24 for(int i=0;i<tot;i++) 25 { 26 if(in[e[i].v]>e[i].w && e[i].u!=e[i].v) 27 { 28 pre[e[i].v]=e[i].u; 29 in[e[i].v]=e[i].w; 30 } 31 } 32 in[root]=0; 33 pre[root]=root; 34 for(int i=0;i<vn;i++) 35 { 36 ans+=in[i]; 37 if(in[i]==INF)//这一步可以看出是否存在这样一棵树形图,因此可以略去DFS 38 return -1; 39 } 40 cnt=0; 41 for(int i=0;i<vn;i++) 42 { 43 if(vis[i]==-1) 44 { 45 int t=i; 46 while(vis[t]==-1) 47 { 48 vis[t]=i; 49 t=pre[t]; 50 } 51 if(vis[t]!=i || t==root) continue; 52 for(int j=pre[t];j!=t;j=pre[j]) 53 id[j]=cnt; 54 id[t]=cnt++; 55 } 56 } 57 if(cnt==0) break; 58 for(int i=0;i<vn;i++) 59 if(id[i]==-1) 60 id[i]=cnt++; 61 for(int i=0;i<tot;i++) 62 { 63 int u,v; 64 u=e[i].u; 65 v=e[i].v; 66 e[i].u=id[u]; 67 e[i].v=id[v]; 68 e[i].w-=in[v]; 69 } 70 vn=cnt; 71 root=id[root]; 72 } 73 return ans; 74 } 75 76 struct Node 77 { 78 int a,b,c; 79 }nd[N]; 80 int main() 81 { 82 //freopen("test.txt","r",stdin); 83 int n,x,y,z,i,j,k,d; 84 while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF) 85 { 86 if(!n) break; 87 tot=0; 88 for(i=1;i<=n;i++) 89 { 90 scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c); 91 adde(0,i,nd[i].c*x); 92 } 93 for(i=1;i<=n;i++) 94 { 95 scanf("%d",&k); 96 while(k--) 97 { 98 scanf("%d",&j); 99 if(i==j) continue; 100 d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c); 101 d*=y; 102 if(nd[i].c<nd[j].c) d+=z; 103 adde(i,j,d); 104 } 105 } 106 int ans=zhuliu(0,n+1); 107 if(ans==-1) printf("poor XiaoA\n"); 108 else printf("%d\n",ans); 109 } 110 return 0; 111 }
View Code
下面是邻接矩阵建图的模版,虽然超时了。但是模版还是有借鉴意义的。模版来自哈工大出版的《图论及应用》。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int N = 1010, INF=0x3f3f3f3f; 6 int Map[N][N]; 7 bool vis[N],f[N]; 8 //f是缩点标记,1表示该点已经被缩掉 9 int pre[N]; 10 int zhuliu(int n) 11 { 12 int sum=0; 13 int i,j,k; 14 for(i=0;i<n;i++) 15 { 16 f[i]=0; 17 Map[i][i]=INF; 18 } 19 pre[0]=0; 20 while(1) 21 { 22 //求最短弧集合E0 23 for(i=1;i<n;i++) 24 { 25 if(f[i]) continue; 26 pre[i]=i; 27 for(j=0;j<n;j++) 28 if(!f[j]&&Map[j][i]<Map[pre[i]][i]) pre[i]=j; 29 if(pre[i]==i) return -1; //没有入边,不存在最小树形图 30 } 31 //检查E0 32 for(i=1;i<n;i++) 33 { 34 if(f[i]) continue ; 35 //从当前点开始找环 36 for(j=0;j<n;j++) vis[j]=0; 37 vis[0]=1; 38 j=i; 39 do 40 { 41 vis[j]=1; 42 j=pre[j]; 43 } 44 while(!vis[j]) ; 45 if(!j) continue; //没有找到环 46 //收缩G中的有向环 47 i=j; 48 //将整个环的权值保存,累计入原图的最小树形图 49 do 50 { 51 sum+=Map[pre[j]][j]; 52 j=pre[j]; 53 } 54 while(j!=i) ; 55 j=i; 56 //对与环上的点有关的边,修改边权 57 do 58 { 59 for(k=0; k<n; k++) 60 if(!f[k]&&Map[k][j]<INF&&k!=pre[j]) 61 Map[k][j]-= Map[pre[j]][j]; 62 j=pre[j]; 63 } 64 while(j!=i) ; 65 //缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i 66 for(j=0;j<n;j++) 67 { 68 if(j==i) continue; 69 for(k=pre[i]; k!=i; k=pre[k]) 70 { 71 if(Map[k][j]<Map[i][j]) Map[i][j] =Map[k][j]; 72 if(Map[j][k]<Map[j][i]) Map[j][i] =Map[j][k]; 73 } 74 } 75 //标记环上其他的点为被缩掉 76 for(j=pre[i];j!=i;j=pre[j]) f[j] =1; 77 //当前环缩点结束,形成新的图G’,跳出继续求G’的最小树形图 78 break; 79 } 80 //如果所有的点都被检查且没有环存在,现在的最短弧集合E0就是 81 //最小树形图,累计如sum, 算法结束 82 if(i==n) 83 { 84 for(i=1;i<n;i++) if(!f[i]) sum+=Map[pre[i]][i]; 85 break; 86 } 87 } 88 return sum; 89 } 90 91 struct node 92 { 93 int a,b,c; 94 }nd[N]; 95 int main() 96 { 97 //freopen("test.txt","r",stdin); 98 int n,x,y,z,i,j,k,d; 99 while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF) 100 { 101 if(!n) break; 102 for(i=0;i<=n;i++) 103 for(j=0;j<i;j++) 104 Map[j][i]=Map[i][j]=INF; 105 for(i=1;i<=n;i++) 106 { 107 scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c); 108 Map[0][i]=nd[i].c*x; 109 } 110 for(i=1;i<=n;i++) 111 { 112 scanf("%d",&k); 113 while(k--) 114 { 115 scanf("%d",&j); 116 if(i==j) continue; 117 d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c); 118 d*=y; 119 if(nd[i].c>=nd[j].c) d+=z; 120 Map[i][j]=min(d,Map[i][j]); 121 } 122 } 123 printf("%d\n",zhuliu(n+1)); 124 } 125 return 0; 126 }
View Code
转载于:https://www.cnblogs.com/Potato-lover/p/3942321.html
hdu4009 Transfer water 最小树形图相关推荐
- kuangbin专题八 HDU4009 Transfer water (无定根最小树形图)
题意: 在山上有N户人家,每家的坐标为(xi, yi, zi).每户人家要吃水,要么自己打井,花费为X*zi,要么从别人的家引水渠代价为 两家的曼哈顿距离*Y,如果这家的海拔比供水的低,还要另外再买一 ...
- hdu 4009 Transfer water(最小树形图模板)
题目链接:点击打开链接 Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Ja ...
- HDU 4009 Transfer water (最小树形图+虚根)
题意:有一个村庄需要修建供水系统.每户居民的房子都有一个三维坐标,每户居民可以选择自己挖井或者从其他居民家里引水.挖水井和引水分别需要花费不同的钱.每户居民有一个意愿表,只愿意对表内的居民家供水.最后 ...
- HDU4009(最小树形图)
对最小树形图做个小小的总结: 1:清除自环,自环是不可能存在于任何最小树形图中的: 2:求出每个顶点的的最小入边: 3:判断该图是否存在最小树形图,由 1 可以判定,或者以图中顶点v作为根节点遍历该图 ...
- TJU 2248. Channel Design 最小树形图
最小树形图,測模版.... 2248. Channel Design Time Limit: 1.0 Seconds Memory Limit: 65536K Total Runs: 2199 ...
- NOI数据结构:最小树形图
最小树形图-朱刘算法详解 +例题解析 最小树形图-朱刘算法详解 +例题解析_pursuit的博客-CSDN博客_最小树形图 图论 -- 生成树 -- 最小树形图 图论 -- 生成树 -- 最小树形图_ ...
- TJU 2248. Channel Design 最小树形图
最小树形图,測模版.... 2248. Channel Design Time Limit: 1.0 Seconds Memory Limit: 65536K Total Runs: 2199 ...
- 最小树形图及其生产方法
诸位看官,这是我第一次在整篇文章的所有图片里面加水印.小弟写博客的时间不长,就有两篇博客被盗用并未注明原文网址.这一方面使我痛心不已,另一方面迫使我不得不重新考虑一下版权保护问题.小弟不是吝啬鬼,如果 ...
- poj3164(最小树形图模版)
对最小树形图做个小小的总结: 1:清除自环,自环是不可能存在于任何最小树形图中的: 2:求出每个顶点的的最小入边: 3:判断该图是否存在最小树形图,由 1 可以判定,或者以图中顶点v作为根节点遍历该图 ...
- HDU6141(最小树形图)
对最小树形图做个小小的总结: 1:清除自环,自环是不可能存在于任何最小树形图中的: 2:求出每个顶点的的最小入边: 3:判断该图是否存在最小树形图,由 1 可以判定,或者以图中顶点v作为根节点遍历该图 ...
最新文章
- Javascript Patterns--读书笔记8 (Factory)
- python爬大学生就业信息报告_Python程序员招聘市场简要报告
- php 二维数组去重
- 关于高性能负载均衡架构,这些知识点大多数人不知道!
- mac mysql read only_mac Read-Only filesystem
- 【Docker】在CentOS上安装
- 黑马程序员-java学习笔记_整理黑马官网Java自学27天基础视频及笔记
- 使用jQuery回到顶部
- 电脑同时打开多个软件如何设置
- 第六篇:A133 用DragonSN工具刷SN号,MAC地址细节问题
- 结构光的概念及其实现三维成像的主要原理
- 分门别类刷leetcode——递归和回溯搜索(C++实现)
- 稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB
- c++win32项目 如何显示后再删除一个绘图_CAD提高绘图效率的秘诀在这里
- php sphinx应用场景,Sphinx+Scws 搭建千万级准实时搜索应用场景详解
- 论文笔记及Pytorch复现:A Dual-Stage Attention-Based Recurrent Neural Network for Time Series Prediction
- php安装教程_php教程
- vs2010 玩转金山界面库 (2) 应用基础
- 内网安全-ew工具使用之端口转发
- jQuery_01_选择器_事件