最小生成树的思维好题
来源:互联网 发布:棋盘分割算法优缺点 编辑:程序博客网 时间:2024/05/16 21:30
前言:
这几天做了几道最小生成树的好题,分享一下。顺便写在这里提醒我:prim算法计算剩余最小边时要用一个数组记录维护,松弛时再更改,才能
T1 Starway:
好题。你考虑如果现在我们定一个答案,那么我们人就可以变成一个园啦,如果走不动,那么拦住他的就是由那几个星星练成的一条路径,(想想一个胖子被门卡住走不动的样子,这个门就是星星或边界)。那么每个点再与上下边界连表,就变成了最小生成树。这是完全图,用Prim,然后边存不下,就可以先不存,扫的时候在算,然后更新后才加边。这样还不用打标记,造好了图直接跑就可以啦。(也可以用最短路,只不过松弛时改一下条件)
代码在另一篇博客中:传送门
T2 货车运输:
就是我们要求路径上最短边权的最大值,那么就是一个最大生成树。建好图后在搞个Lca就好啦。顺便写一写倍增。
代码:
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int size = 10005;const int inf = 2002093000;struct EDGE{ int fr , to , next , val; inline bool operator < (const EDGE &a) const { return val > a.val; }}edge [10 * size] ; int cnt = 0;int fa[size] , head[size] ;int d[size] ;int f[size][20] , g[size][20];int n , m , q , num = 1 ;void adde(int fr , int to , int val){ edge[++cnt] = (EDGE){fr , to , head[fr] , val }; head[fr] = cnt ;}void addedge(int fr , int to , int val){ adde(fr , to , val); adde(to , fr , val);}int find(int x){ if (fa[x] == x) return x; else return fa[x] = find( fa[x] ); }bool unio(int x,int y){ x = find(x) ; y = find(y); if (x != y) { fa[x] = y ; return true;} else return false; }void dfs(int node , int fa ){ d[node] = d[fa] + 1; for (int i = head[node] ; i ; i = edge[i].next) if ( edge[i].to != fa ) { f[ edge[i].to ][ 0 ] = node; g[ edge[i].to ][ 0 ] = edge[i].val; dfs(edge[i].to , node ); }}int lca(int x,int y){ int ans = inf; if (d[x] < d[y]) swap(x , y); int del = d[x] - d[y]; //printf("x is %d y is %d del is %d\n",x,y,del); for (int i = 15; i >= 0;i--) if (del & (1 << i) ) { ans = min(ans , g[x][i]); x = f[x][i]; } if ( x == y ) return ans; for (int i = 15 ; i >= 0 ; i--) if ( f[x][i] != f[y][i] ) { ans = min(ans , min( g[x][i] , g[y][i] ) ); x = f[x][i] ; y = f[y][i] ; } return f[x][0] == 0 ? -1 : min(ans , g[x][0]);}int main(){ scanf("%d%d" , &n , &m); for (int i = 1 ; i <= m ; i++) scanf("%d%d%d" , &edge[i].fr , &edge[i].to , &edge[i].val); cnt = m ; sort(edge + 1 , edge + 1 + cnt); for (int i = 1 ; i <= n ; i++ ) fa[i] = i; for (int i = 1 ; i <= m ; i++ ) { if ( unio ( edge[i].to , edge[i].fr ) ) { addedge( edge[i].fr , edge[i].to , edge[i].val ); } } memset(f,0,sizeof f);memset(g , 0 , sizeof g); dfs ( 1 , 0 ) ; for (int j = 1 ; j <= 15 ; j++) for (int i = 1 ; i <= n ; i++) { //printf("%d %d %d %d\n ", i , j,f[i][j-1],g[i][j-1]); f[i][j] = f[ f[i][j-1] ] [ j-1 ]; g[i][j] = min( g[i][ j-1 ] , g[ f[i][j-1] ][ j-1 ] ); } /*for (int i = 1; i <= n;i++) { printf("%d is ",i); for (int j = 0;j <= 3;j++) printf("%d ",f[i][j]); printf("\n"); } /*for (int i = 1;i<=cnt;i++) printf("%d is %d\n",i,edge[i].val);*/ scanf("%d" , &q); for (int i = 1 ; i <= q ; i++) { int x,y; scanf("%d%d" , &x , &y); printf("%d\n",lca(x,y)); } return 0;}
T3 大逃亡:
这道题把我坑住的地方就是可以
代码(工程级别):
#include<cstdio>#include<algorithm>#include <queue>#include<cstring>using namespace std;typedef long long ll;const int size = 1005;const int inf = 20010910;struct CD{ int x , y;}dot[size * 10];int n;struct que{ int x , y , fa;};int x,y,stx,sty,edx,edy,step;int d[size][size] ;//bool vis[size][size] ;int ans = 0;int dist(int xx,int yy,int xxx,int yyy) { return abs(xx-xxx) + abs(yy-yyy); }int dist(CD a,CD b) { return abs(a.x-b.x) + abs(a.y - b.y); }int read(){ int flag = 1 , x = 1; char s = getchar(); while (s < '0' || s > '9') {if (s=='-') flag = -1;s = getchar();} while ('0'<=s && s<='9') {x = x*10 + s - '0' ; s = getchar();} return flag * x;}void predo()// bfs 1{ queue <que> q; for (int i = 0;i < x; i++) for (int j = 0;j < y; j++) d[i][j] = inf; for (int i = 1;i <= n ; i++) { q.push( (que) {dot[i].x , dot[i].y , i} ); d[ dot[i].x ][ dot[i].y ] = 0; } while (!q.empty()) { que cur = q.front(); if (cur.x < x - 1) if (d[ cur.x + 1 ][ cur.y] == inf) { d[ cur.x + 1 ][ cur.y ] = dist( dot[cur.fa].x , dot[cur.fa].y , cur.x + 1 , cur.y ); q.push( (que) {cur.x + 1 , cur.y , cur.fa}); } if (cur.x > 0) if (d[ cur.x - 1 ][ cur.y] == inf) { d[ cur.x - 1 ][ cur.y ] = dist( dot[cur.fa].x , dot[cur.fa].y , cur.x - 1 , cur.y ); q.push( (que) {cur.x - 1 , cur.y , cur.fa}); } if (cur.y < y - 1) if (d[ cur.x ][ cur.y + 1 ] == inf) { d[ cur.x ][ cur.y + 1 ] = dist( dot[cur.fa].x , dot[cur.fa].y , cur.x , cur.y + 1); q.push( (que) {cur.x , cur.y + 1 , cur.fa}); } if (cur.y > 0) if (d[ cur.x ][ cur.y - 1 ] == inf) { d[ cur.x ][ cur.y - 1 ] = dist( dot[cur.fa].x , dot[cur.fa].y , cur.x , cur.y - 1); q.push( (que) {cur.x , cur.y - 1 , cur.fa}); } q.pop(); }}void init(){ n = read(); x = read(); y= read() , stx = read(), sty = read(), edx = read() , edy = read(); for (int i = 1;i <= n; i++) dot[i].x = read() , dot[i].y = read();}bool check(int limit){ bool vis[size][size]; memset(vis , false , sizeof vis); vis[stx][sty] = 1; queue <CD> q; q.push( (CD) {stx , sty} ); while (!q.empty()) { CD cur = q.front(); if (cur.x < x - 1) if (d[ cur.x + 1 ][ cur.y] >= limit && !vis[ cur.x + 1 ][ cur.y]) { vis[ cur.x + 1 ][ cur.y ] = true ; q.push( (CD) {cur.x + 1 , cur.y }); } if (cur.x > 0) if (d[ cur.x - 1 ][ cur.y] >= limit && !vis[ cur.x - 1 ][ cur.y]) { vis[ cur.x - 1 ][ cur.y ] = true ; q.push( (CD) {cur.x - 1 , cur.y }); } if (cur.y < y - 1) if (d[ cur.x ][ cur.y + 1 ] >= limit && !vis[ cur.x ][ cur.y + 1]) { vis[ cur.x ][ cur.y + 1 ] = true; q.push( (CD) {cur.x , cur.y + 1 }); } if (cur.y > 0) if (d[ cur.x ][ cur.y - 1 ] >= limit && !vis[ cur.x ][ cur.y - 1]) { vis[ cur.x ][ cur.y - 1 ] = true ; q.push( (CD) {cur.x , cur.y - 1 }); } q.pop(); } if (!vis[edx][edy]) return false; else return true;}void half(){ int l = 0 , r = min(d[edx][edy] , d[stx][sty]); while (l <= r) { int mid = l + r >> 1; if (check(mid)) { l = mid + 1; ans= mid ; } else r = mid - 1; } }#define len faint find(int limit){ bool vis[size][size];memset(vis,false,sizeof vis);vis[stx][sty] = true; queue <que> q;q.push( (que) {stx , sty , 0} ); while (!q.empty()) { que cur = q.front(); if (cur.x < x - 1) if (d[ cur.x + 1 ][ cur.y] >= limit && !vis[ cur.x + 1 ][ cur.y]) { vis[ cur.x + 1 ][ cur.y ] = true ; if (cur.x + 1 == edx && cur.y == edy) return (cur.len + 1); q.push( (que) {cur.x + 1 , cur.y ,cur.len + 1}); } if (cur.x > 0) if (d[ cur.x - 1 ][ cur.y] >= limit && !vis[ cur.x - 1 ][ cur.y]) { vis[ cur.x - 1 ][ cur.y ] = true ; if (cur.x - 1 == edx && cur.y == edy) return (cur.len + 1); q.push( (que) {cur.x - 1 , cur.y ,cur.len + 1}); } if (cur.y < y - 1) if (d[ cur.x ][ cur.y + 1 ] >= limit && !vis[ cur.x ][ cur.y + 1]) { vis[ cur.x ][ cur.y + 1 ] = true; if (cur.x == edx && cur.y + 1 == edy) return (cur.len + 1); q.push( (que) {cur.x , cur.y + 1 ,cur.len + 1}); } if (cur.y > 0) if (d[ cur.x ][ cur.y - 1 ] >= limit && !vis[ cur.x ][ cur.y - 1]) { vis[ cur.x ][ cur.y - 1 ] = true ; if (cur.x == edx && cur.y -1 == edy) return (cur.len + 1); q.push( (que) {cur.x , cur.y - 1 ,cur.len + 1}); } q.pop(); }}int main(){ init(); predo(); half ();step = find(ans); printf("%d %d" , ans , step); return 0;}
结语
考思维的题果然好啊,我感觉学到了很多,尤其是套路。
阅读全文
0 0
- 最小生成树的思维好题
- Fzu 2254 英语考试【思维+最小生成树】好题~
- Codeforces 606 D Lazy Student【逆最小生成树+思维】好题
- 最小生成树思维导图
- 【最小生成树--思维】fzu 2254 英语考试;
- 比较好的题目“典型的最小生成树”
- 蓝桥杯练习题 最小方差生成树 (Kruskal MST 好题)
- 【POJ】2349 - Arctic Network(最小生成树的第n条大边)(好题)
- Hdu 5253 连接的管道【思维建图+最小生成树】
- BZOJ(本校) 2666 中继系统 - 思维&最小生成树
- CSU 1541 There is No Alternative【最小生成树+思维】
- POJ 2349 Arctic Network【中文版题目】【最小生成树+思维】
- 【POJ 1789】Truck History(思维,最小生成树)
- Fzu 2185 树的路径覆盖【思维+贪心】好题~
- 特殊的排序(思维好题)
- UVA1279,Asteroid Rangers,星际游击队,好烦的最小生成树
- WUST 1947 联络员(最小生成树+部分连好的点)
- 典型的最小生成树题
- 网页数据存储mysql数据库过程问题及解决
- C++笔记——引用&
- 一部Web应用自动化部署的进化史[AWS]
- Ubuntu16.04+opencv3.2.0+python 版本切换
- Understanding and Visualizing Convolutional Neural Networks
- 最小生成树的思维好题
- VMware-vSphere-5.1--------群集、HA、DRS、FT
- TI cc2541协议栈开发环境的搭建
- dijkstra队列优化链式前向星(C++、Java)
- windows下用navicat远程链接虚拟机Linux下MySQL数据库
- 两边空格的编程风格
- 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
- Sql Server系列:视图
- 动态库和静态库