hdu4966 hdu4009 (最小树形图)
来源:互联网 发布:linux 查看目录大小 编辑:程序博客网 时间:2024/05/19 10:41
hdu4966
一开始以为是网络流,各种坑队友,后来才发现是相当裸的最小树形图。
添加一个根,连边到各课程的0级,权值为0。
然后每个课程从(i)级连边到(i-1)级,权值为0.
最后根据课程间的关系再连边。
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 555, maxm = 500 * 2000, inf = 1e9;struct Edge{ int u, v, w; Edge(){} Edge(int u, int v, int w): u(u), v(v), w(w){}}e[maxm];int ec;int lev[55], begid[55], endid[55];int N;int mincost[maxn], pre[maxn];bool makeMin(int root){ for(int i = 1; i <= N; i++) mincost[i] = inf; for(int i = 0; i < ec; i++){ if(e[i].u == e[i].v) continue; int v = e[i].v; if(mincost[v] > e[i].w){ mincost[v] = e[i].w; pre[v] = e[i].u; } } for(int i = 1; i <= N; i++){ if(i == root) continue; if(mincost[i] == inf) return false; } return true;}int vis[maxn];int id[maxn];bool existCircle(int root, int &res){ memset(vis, -1, sizeof(vis)); memset(id, -1, sizeof(id)); int ind = 1; mincost[root] = 0; for(int i = 1; i <= N; i++){ int v = i; res += mincost[i]; while(vis[v] != i && v != root && id[v] == -1) { vis[v] = i, v = pre[v]; } if(v != root && id[v] == -1){ for(int u = pre[v]; u != v; u = pre[u]) id[u] = ind; id[v] = ind++; } } if(ind == 1) return false; for(int i = 1; i <= N; i++) if(id[i] == -1) id[i] = ind++; N = ind - 1; return true;}void update(){ for(int i = 0; i < ec; i++){ int v = e[i].v; e[i].u = id[e[i].u]; e[i].v = id[e[i].v]; if(e[i].u == e[i].v) continue; e[i].w -= mincost[v]; }}int DMST(int root){ int res = 0; while(1){ if(!makeMin(root)) return -1; if(!existCircle(root, res)) return res; update(); root = id[root]; } return -1;}int main(){// freopen("in", "r", stdin);// freopen("out", "w", stdout); int n, m; while(scanf("%d%d", &n, &m), n&&m){ for(int i = 1; i <= n; i++) scanf("%d", lev+i); lev[0] = 1, begid[0] = 0; for(int i = 1; i <= n; i++) begid[i] = begid[i-1] + lev[i-1] + 1; N = begid[n] + lev[n]; int c, l, d, r, w; int root = 1; ec = 0; for(int i = 1; i <= n; i++) e[ec++] = Edge(root, begid[i], 0); for(int i = 1; i <= n; i++){ for(int j = 1; j <= lev[i]; j++){ int u = begid[i] + j, v = u - 1; e[ec++] = Edge(u, v, 0); } } for(int i = 0; i < m; i++){ scanf("%d%d%d%d%d", &c, &l, &d, &r, &w); int v = begid[d] + r; for(int j = l, u = begid[c] + l; j <= lev[c]; u++, j++){ e[ec++] = Edge(u, v, w); } } int ans = DMST(root); if(~ans) printf("%d\n", ans); else puts("-1"); } return 0;}
hdu4009
一个村子有n个房子,每间房子的坐标为(x,y,z)
如果自己打井,则代价为 z * A
如果从别的房子那里连水管过来,则代价为 两点的曼哈顿距离*B; 如果源点的z比此地的z小,则代价要加上C
求让所有房子都有水的最小代价。(怎么样都能保证每个房子都有水,所以根本不会输出“poor XiaoA”...)
加入根,然后根到每个点的权值为该点自己打井的代价,
然后其他的根据输入建边。
一个优化是,如果某个点从其他点连的边代价比直接自己打井还大,那么就可以不连。
然后就是IO输入优化了。
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 1002, maxm = 1002 * 1004, inf = 0x3f3f3f3f;#define ABS(x) ( (x)>0? (x) : (-(x)) )struct Edge{ int u, v, w; Edge(){} Edge(int u, int v, int w): u(u), v(v), w(w){}}e[maxm];int ec;int N;int mincost[maxn], pre[maxn];bool makeMin(int root){ memset(mincost, 0x3f, sizeof(mincost)); for(int i = 0; i < ec; i++){ if(e[i].u == e[i].v) continue; int v = e[i].v; if(mincost[v] > e[i].w){ mincost[v] = e[i].w; pre[v] = e[i].u; } } for(int i = 1; i <= N; i++){ if(i == root) continue; if(mincost[i] == inf) return false; } return true;}int vis[maxn];int id[maxn];bool existCircle(int root, int &res){ memset(vis, -1, sizeof(vis)); memset(id, -1, sizeof(id)); int ind = 1; mincost[root] = 0; for(int i = 1; i <= N; i++){ int v = i; res += mincost[i]; while(vis[v] != i && v != root && id[v] == -1) { vis[v] = i, v = pre[v]; } if(v != root && id[v] == -1){ for(int u = pre[v]; u != v; u = pre[u]) id[u] = ind; id[v] = ind++; } } if(ind == 1) return false; for(int i = 1; i <= N; i++) if(id[i] == -1) id[i] = ind++; N = ind - 1; return true;}void update(){ for(int i = 0; i < ec; i++){ int v = e[i].v; e[i].u = id[e[i].u]; e[i].v = id[e[i].v]; if(e[i].u == e[i].v) continue; e[i].w -= mincost[v]; }}int DMST(int root){ int res = 0; while(1){ if(!makeMin(root)) return -1; if(!existCircle(root, res)) return res; update(); root = id[root]; } return -1;}struct Pos{ int x, y, z;}p[maxn];inline int dis(const Pos& a, const Pos& b){ return ABS(a.x-b.x) + ABS(a.y-b.y) + ABS(a.z-b.z); }inline int nextInt(){ char ch = ' '; int res = 0; while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)){ res *= 10; res += ch - '0'; ch = getchar(); } return res;}int self[maxn];int main(){// freopen("in.txt", "r", stdin);// freopen("out", "w", stdout); int n, x, y, z; while(n = nextInt(), x = nextInt(), y = nextInt(), z = nextInt(), n && x && y && z){ ec = 0; N = n + 1; for(int i = 1; i <= n; i++) { p[i].x = nextInt(); p[i].y = nextInt(); p[i].z = nextInt(); } for(int i = 1; i <= n; i++){ self[i] = p[i].z * x; e[ec++] = Edge(N, i, self[i]); } for(int i = 1; i <= n; i++){ int k; k = nextInt(); for(int j = 0, v, w; j < k; j++){ v = nextInt(); if(v == i) continue; w = dis(p[i], p[v]); w *= y; if(p[i].z < p[v].z) w += z; if(w >= self[v]) continue; e[ec++] = Edge(i, v, w); } } printf("%d\n", DMST(N)); } return 0;}
0 0
- hdu4966 hdu4009 (最小树形图)
- 最小树形图(hdu4009)
- 最小树形图 hdu4966
- 2014多校9(1007)hdu4966(最小树形图)
- hdu4966 最小树形图(最少辅导花费)
- 最小树形图(hdu4966多校联赛9)
- hdu4009 Transfer water ( 最小树形图的模板 )
- hdu4966 GGS-DDU --- 最小树形图
- hdu4966 最小树形图 /刘朱算法
- HDU4966 GGS-DDU【最小树形图】
- HDU4009 Transfer water 【最小树形图】
- HDU4009 Transfer water【最小树形图】【不定根】
- hdu4009 Transfer water(最小树形图模板)
- HDU4009 Transfer water(最小树形图)
- HDU4009 最小树形图 有向最小生成树
- 有向图的最小生成树(最小树形图)hdu4009 2011大连赛区网络赛1009
- 【hdu4009】【建模】【有向图的最小生成树】
- HDU4966
- 发几个比较重要的链接
- HBase如何实现多条件查询
- TCP/IP之四书五经
- 安卓基础入门-------第一天
- lex创建词法分析程序
- hdu4966 hdu4009 (最小树形图)
- An Easy Problem!
- java数据结构学习感悟之java中指针的使用
- English---There is / There are
- 图 - 最短路径
- 在Mybatis中使用注解@多个参数查询
- 安装hadoop之前的准备(配置linux)
- PHP缓存之模块缓存(APC)
- 图 - 拓扑排序