【牛客 - 370B】Rinne Loves Graph(分层图最短路 或 最短路dp)

题干:
 

Island 发生了一场暴乱!现在 Rinne 要和 Setsuna 立马到地上世界去。

众所周知:Island 是有一些奇怪的城镇和道路构成的(题目需要,游戏党勿喷),有些城镇之间用双向道路连接起来了,且每条道路有它自己的距离。但是有一些城镇已经被派兵戒严,虽然主角可以逆天改命强闯,但是为了体验该游戏的平衡性,他们只能穿过不超过 K 次被戒严的城镇。

定义“穿过”:从一个戒严的点出发到达任意一个点,都会使得次数加1

现在他们想从 1 号城镇最快的走到 n 号城镇(即出口),现在他们想让你告诉他们最短需要走多少路。

输入描述:

第一行三个整数 n,m,k,分别表示城镇数量,边数量和最多能闯过被戒严的城市的次数。
接下来 n 行,每行一个整数 1 或 0,如果为 1 则表示该城市已被戒严,0 则表示相反。
接下来 m 行,每行三个数 u,v,w,表示在 u 城镇和 v 城镇之间有一条长度为 w 的双向道路。

输出描述:

输出一行一个数字,表示从 1 到 n 的最短路径,如果到达不了的话,请输出 -1。

示例1

输入

复制

4 5 1
1
0
1
0
1 2 10
2 3 10
3 1 15
1 4 60
3 4 30

输出

复制

60

备注:

2≤n≤800,1≤m≤4000,1≤k≤10,1≤w≤1062≤n≤800,1≤m≤4000,1≤k≤10,1≤w≤106

保证没有多条道路连接同一对城市,也没有一条道路连向自己。

解题报告:

这题可以dp,dp[i][j]表示从1到 i ,穿过j次戒烟戒严城镇,的最短路。(最近这种题见了三道了。)。也可以k - 分层图。(下面有好几个分层图代码,建图方式和做法有所不同)。也可以直接类似bfs的Dijkstra。。

AC代码1:(分层图)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 800 + 5;
const int INF = 0x3f3f3f3f;
int tot;
int n,m,k;
int a[MAX];
int dis[MAX*15],head[MAX*15];
bool vis[MAX*15];
struct Edge {int to,ne;int w;
} e[8005*15];
struct Point {int id;int c;Point() {}Point(int id,int c):id(id),c(c) {}bool operator <(const Point & b) const {return c>b.c;}
};
void add(int u,int v,int w) {e[++tot].to = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot;
}
void Dijkstra() {memset(dis,INF,sizeof dis);dis[1] = 0;priority_queue<Point> pq;pq.push(Point(1,0));while(pq.size()) {Point cur = pq.top(); pq.pop();
//        if(vis[cur.id]) continue;这两句加不加都可以AC
//        vis[cur.id] = 1;for(int i = head[cur.id]; i!=-1; i = e[i].ne) {if(dis[e[i].to]>e[i].w+cur.c) {dis[e[i].to]=e[i].w+cur.c;pq.push(Point(e[i].to,dis[e[i].to]));}}}
}int main()
{memset(head,-1,sizeof head);scanf("%d%d%d",&n,&m,&k);for (int i=1; i<=n; i++) scanf("%d",&a[i]);for (int i=1; i<=m; i++) {int x,y,w;scanf("%d%d%d",&x,&y,&w);if(!a[x]) {for(int j = 0; j<=k; j++) add(x+n*j,y+n*j,w);}if(!a[y]) {for(int j = 0; j<=k; j++) add(y+n*j,x+n*j,w);}if(a[x]) {for(int j = 0; j<k; j++) add(x+n*j,y+n*(j+1),w);}if(a[y]) {for(int j = 0; j<k; j++) add(y+n*j,x+n*(j+1),w);}      }if (k<0) {printf("-1\n");return 0;}Dijkstra();int ans = INF;for (int i = 1; i<=k+1; i++) ans=min(ans,dis[i*n]);if (ans == INF) ans = -1;printf("%d\n",ans);return 0 ;
}

一个大佬的分层图:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=2e5+10;
int a[N],he[N*10],t[N*20],ne[N*20],d[N*400],vis[N*10],tot=0;
long long dis[N],cc[N*20];
void link(int x,int y,long long z)
{tot++;ne[tot]=he[x];he[x]=tot;t[tot]=y;cc[tot]=z;
}
int main()
{int n,m,k;scanf("%d%d%d",&n,&m,&k);for (int i=1;i<=n;i++) scanf("%d",&a[i]);if (a[1]) k--;if (a[n]) k++;for (int i=1;i<=m;i++){int x,y;long long z;scanf("%d%d%lld",&x,&y,&z);for (int j=0;j<=k;j++){if (!a[x]) link(y+n*j,x+n*j,z);if (!a[y]) link(x+n*j,y+n*j,z);}for (int j=0;j<k;j++){if (a[x]) link(y+n*j,x+n*(j+1),z);if (a[y]) link(x+n*j,y+n*(j+1),z);}}if (k<0){printf("-1\n");return 0;}int i=0,kk=1;d[1]=1;dis[1]=0;for (int i=2;i<=n*(k+1);i++) dis[i]=(long long)m*40000000;i=0;while (i<kk){i++;int u=d[i];for (int j=he[u];j;j=ne[j]){if (dis[u]+cc[j]<dis[t[j]]){dis[t[j]]=dis[u]+cc[j];kk++;d[kk]=t[j];}}}long long ans=(long long)m*40000000;for (int i=1;i<=k+1;i++) ans=min(ans,dis[i*n]);if (ans==(long long)m*40000000) ans=-1;printf("%lld\n",ans);

分层图标程:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define LL long longconst int MAXN = 800 + 5;
const int MAXM = 4000 + 5;
const int MAXK = 10 + 5;int N,M,K;
using std::queue;struct Node{struct Edge *firstEdge;LL dist;bool inQueue,die;
}node[MAXN * MAXN + 2];struct Edge{Node *s,*t;LL w;Edge *next;
}pool[MAXM * MAXK * 2],*frog = pool;Edge *New(Node *s,Node *t,LL w){Edge *ret = ++frog;ret->s = s;ret->t = t;ret->w = w;ret->next = s->firstEdge;return ret;
}inline void add(int u,int v,LL w){node[u].firstEdge = New(&node[u],&node[v],w);//node[v].firstEdge = New(&node[v],&node[u],w);
}LL SPFA(int s,int t,int n){for(int i = 1;i <= n;i++){node[i].dist = LLONG_MAX;node[i].inQueue = false;}queue<Node *> q;q.push(&node[s]);node[s].inQueue = true;node[s].dist = 0;while(!q.empty()){Node *v = q.front();q.pop();v->inQueue = false;for(Edge *e = v->firstEdge;e;e = e->next){if(e->t->dist > v->dist + e->w){e->t->dist = v->dist + e->w;if(!e->t->inQueue){e->t->inQueue = true;q.push(e->t);}}}}return node[t].dist;
}int main(){scanf("%d%d%d",&N,&M,&K);for(int x,i = 1;i <= N;i++)scanf("%d",&node[i].die);int s = 0,t = N + N * K + 1;for(int u,v,i = 1;i <= M;i++){LL w;scanf("%d%d%lld",&u,&v,&w);if(!node[u].die)for(int i = 0;i <= K;i++)add(u + N * i,v + N * i,w);if(!node[v].die)for(int i = 0;i <= K;i++)add(v + N * i,u + N * i,w);if(node[u].die)for(int i = 0;i < K;i++)add(u + N * i,v + N * (i + 1),w);if(node[v].die)for(int i = 0;i < K;i++)add(v + N * i,u + N * (i + 1),w);}add(s,1,0);for(int i = 0;i <= K;i++)add(N + (N * i),t,0);LL ans = SPFA(s,t,N*(1 + K) + 2);printf("%lld\n",(ans == LLONG_MAX) ? -1 : ans);//getchar();getchar();return 0;
}

AC代码3:(最短路dp)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 800 + 5;
const int INF = 0x3f3f3f3f;
int tot;
int n,m,k;
int a[MAX];
int dis[MAX][15],head[MAX];//dis[i][j]表示从1到 i ,穿过j次戒烟戒严城镇,的最短路。
struct Edge {int to,ne;int w;
} e[4005*2];
struct Point {int id;int c,jy;Point() {}Point(int id,int c,int jy):id(id),c(c),jy(jy) {}bool operator <(const Point & b) const {return c>b.c;}
};
void add(int u,int v,int w) {e[++tot].to = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot;
}
void Dijkstra() {memset(dis,INF,sizeof dis);dis[1][0] = 0;priority_queue<Point> pq;pq.push(Point(1,0,0));while(pq.size()) {Point cur = pq.top();pq.pop();for(int i = head[cur.id]; i!=-1; i = e[i].ne) {int nowjy = a[cur.id] + cur.jy;if( nowjy > k) continue;if(dis[e[i].to][nowjy]>e[i].w+cur.c) {dis[e[i].to][nowjy]=e[i].w+cur.c;pq.push(Point(e[i].to,dis[e[i].to][nowjy],nowjy));}}}}
int main() {cin>>n>>m>>k;for(int i = 1; i<=n; i++) scanf("%d",a+i);memset(head,-1,sizeof head);for(int x,y,w,i = 1; i<=m; i++) {scanf("%d%d%d",&x,&y,&w);add(x,y,w);add(y,x,w);}Dijkstra();int ans = INF;for(int i=0; i<=k; i++) {ans=min(ans,dis[n][i]);}if(ans==INF) puts("-1");else printf("%d\n",ans);return 0 ;
}

当然你如果认准了那道“小明的贪心题”,加上这个判断也无妨(为了避免同一元素多次入队):

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 800 + 5;
const int INF = 0x3f3f3f3f;
int tot;
int n,m,k;
int a[MAX];
int dis[MAX][15],head[MAX];
struct Edge {int to,ne;int w;
} e[8005];
struct Point {int id;int c,jy;Point() {}Point(int id,int c,int jy):id(id),c(c),jy(jy) {}bool operator <(const Point & b) const {return c>b.c;}
};
void add(int u,int v,int w) {e[++tot].to = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot;
}
void Dijkstra() {memset(dis,INF,sizeof dis);dis[1][0] = 0;priority_queue<Point> pq;pq.push(Point(1,0,0));while(pq.size()) {Point cur = pq.top();pq.pop();if(cur.c > dis[cur.id][cur.jy]) continue;for(int i = head[cur.id]; i!=-1; i = e[i].ne) {int nowjy = a[cur.id] + cur.jy;if( nowjy > k) continue;if(dis[e[i].to][nowjy]>e[i].w+cur.c) {dis[e[i].to][nowjy]=e[i].w+cur.c;pq.push(Point(e[i].to,dis[e[i].to][nowjy],nowjy));}}}}
int main() {cin>>n>>m>>k;for(int i = 1; i<=n; i++) scanf("%d",a+i);memset(head,-1,sizeof head);for(int x,y,w,i = 1; i<=m; i++) {scanf("%d%d%d",&x,&y,&w);add(x,y,w);add(y,x,w);}Dijkstra();int ans = INF;for(int i=0; i<=k; i++) {ans=min(ans,dis[n][i]);}if(ans==INF) puts("-1");else printf("%d\n",ans);return 0 ;
}

还可以这么写最短路这题(看起来不像是Dijkstra反倒像是bfs,但又不是bfs):

#include<bits/stdc++.h>
using namespace std;
struct edge {int to, next, w;
} e[8100];
struct node {int u, k, d;node() {}node(int u, int k, int d) : u(u), k(k), d(d) {}bool operator < (const node &a) const {return d > a.d;}
};
int head[888], num;
int jy[888];
int n, m, k;
void add(int u, int v, int w) {e[num].to = v;e[num].next = head[u];e[num].w = w;head[u] = num++;
}
int d[888];
void Dijkstra() {//bfsmemset(d, -1, sizeof d);d[1] = 0;priority_queue<node> q;q.push(node(1, 0, 0));while(!q.empty()) {node cur = q.top();q.pop();if(cur.u == n) {printf("%d\n", d[n]);return;}for(int i=head[cur.u]; i!=-1; i=e[i].next) {int v = e[i].to;if(jy[cur.u] && cur.k == k) continue;if(d[v]==-1|| d[v] > cur.d+e[i].w) {d[v] = cur.d+e[i].w;q.push(node(v,cur.k+jy[cur.u],d[v]));}}}puts("-1");return;
}
int main() {memset(head, -1, sizeof head);num = 0;scanf("%d%d%d",&n,&m,&k);for(int i=1; i<=n; i++) {scanf("%d", &jy[i]);}for(int i=0; i<m; i++) {int u, v, w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}Dijkstra();
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设python中有模块m、如果希望同时导入m中的所有成员_python-模块

先做几个练习题练习计算一个四乘四矩阵的所有元素的和&#xff0c;以及对角线之和#encodingutf-8a[[1,2,3,4],[2,5,2,3],[1,5,3,2],[5,3,2,5]]#encodingutf-8a[[1,2,3,4],[2,5,2,3],[1,5,3,2],[5,3,2,5]]total_sum0diagonal_sum0‘‘‘for i in a:print "i:",ifor j …

【牛客 - 370F】Rinne Loves Edges(树,统计dp)

题干&#xff1a; Rinne 最近了解了如何快速维护可支持插入边删除边的图&#xff0c;并且高效的回答一下奇妙的询问。 她现在拿到了一个 n 个节点 m 条边的无向连通图&#xff0c;每条边有一个边权 wiwi 现在她想玩一个游戏&#xff1a;选取一个 “重要点” S&#xff0c;然…

java 单例 饿汉式_Java-单例设计模式(懒汉与饿汉)

单例设计模式保证一个类在内存中只能有一个对象。思路&#xff1a;1)如果其他程序能够随意用 new 创建该类对象&#xff0c;那么就无法控制个数。因此&#xff0c;不让其他程序用 new 创建该类的对象。2)既然不让其他程序 new 该类对象&#xff0c;那么该类在自己内部就要创建一…

【HYSBZ - 2763 】飞行路线 (分层图最短路,最短路dp)

题干&#xff1a; Alice和Bob现在要乘飞机旅行&#xff0c;他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务&#xff0c;设这些城市分别标记为0到n-1&#xff0c;一共有m种航线&#xff0c;每种航线连接两个城市&#xff0c;并且航线有一定的价格。Alice和…

java 命令行 编译 jar文件_用命令行编译java并生成可执行的jar包

如果想用java编写一个可视化小程序&#xff0c;碰巧手头没有IDE的话&#xff0c;可以用命令行来完成编译、打包等工作。拿自己编写的“java记事本”为例&#xff0c;介绍一下这个过程&#xff1a;1.编写源代码。编写源文件&#xff1a;NotePad.java并保存&#xff0c;例如&…

【牛客 - 369A】小D的剧场(线性dp)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/369/A 来源&#xff1a;牛客网 题目描述 "我明白。" 作为这命运剧场永远的观众&#xff0c;小D一直注视着这片星光璀璨的舞台&#xff0c;舞台上&#xff0c;少女们的身姿演绎出了一幕幕…

java list遍历添加元素_java遍历List过程中添加和删除元素的问题

遍历元素最常见的三种方法&#xff1a;//第三种遍历【利用迭代器】private static void loopList3(List strList) {Iterator itr strList.iterator();while (itr.hasNext()){String tmp itr.next();if("000".equals(tmp)){itr.remove();}else{System.out.println(t…

【蓝桥杯官网试题 - 算法提高 】求最大值 (dp,0-1背包)

题干&#xff1a; 问题描述 给n个有序整数对ai bi&#xff0c;你需要选择一些整数对 使得所有你选定的数的aibi的和最大。并且要求你选定的数对的ai之和非负&#xff0c;bi之和非负。 输入格式 输入的第一行为n&#xff0c;数对的个数   以下n行每行两个整数 ai bi 输出格…

java button 圆角_UIButton具有渐变边框和圆角

我想要的是一个自定义UIButton&#xff0c;它有一个渐变边框(只是边框是渐变)和圆角 . 我几乎到了我想去的地方&#xff0c;但是角落有问题 . 这是我目前拥有的&#xff1a;这是我的代码&#xff1a;override func viewDidLoad() {super.viewDidLoad()let gradient CAGradient…

【牛客 - 368B】选点(dfs序,LIS 或 dfs序 + 树状数组 + 离散化,树状数组求LIS的方法)

题干&#xff1a; 有一棵n个节点的二叉树&#xff0c;1为根节点&#xff0c;每个节点有一个值wi。现在要选出尽量多的点。 对于任意一棵子树&#xff0c;都要满足&#xff1a; 如果选了根节点的话&#xff0c;在这棵子树内选的其他的点都要比根节点的值大&#xff1b; 如…

java xsd 解析 xml文件_Java针对XSD文件验证XML文件的最佳方法是什么?

小编典典Java运行时库支持验证。上次我检查的是幕后的Apache Xerces解析器。你可能应该使用javax.xml.validation.Validator。import javax.xml.XMLConstants;import javax.xml.transform.Source;import javax.xml.transform.stream.StreamSource;import javax.xml.validation.…

*【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流)

题干&#xff1a; You may have heard of the pie rule before. It states that if two people wish to fairly share a slice of pie, one person should cut the slice in half, and the other person should choose who gets which slice. Alice and Bob have many slices …

【牛客 - 318F】关于我转生变成史莱姆这档事(二分,搜索)

题干&#xff1a; 有一天&#xff0c;利姆鲁在这个世界最重要的人静被魔王带走&#xff0c;并将其困在一个n*n的迷宫内的某一处&#xff0c;迷宫的每个格子都可能有一只魔物&#xff0c;魔物的攻击力为a[i][j]&#xff0c;因而利姆鲁只有当攻击力大于等于a[i][j]才能通过这个方…

java获取xlsx某列数据_Java读取Excel指定列的数据详细教程和注意事项

本文使用jxl.jar工具类库实现读取Excel中指定列的数据。jxl.jar是通过java操作excel表格的工具类库&#xff0c;是由java语言开发而成的。这套API是纯Java的&#xff0c;并不依赖Windows系统&#xff0c;即使运行在Linux下&#xff0c;它同样能够正确的处理Excel文件。支持Exce…

【CodeForces - 988C 】Equal Sums (思维,STLmap,STLset,tricks)

题干&#xff1a; You are given kk sequences of integers. The length of the ii-th sequence equals to nini. You have to choose exactly two sequences ii and jj (i≠ji≠j) such that you can remove exactly one element in each of them in such a way that the su…

java quartz 数据库_SpringBoot+Quartz+数据库存储

Spring整合Quartza、quartz调度框架是有内置表的进入quartz的官网http://www.quartz-scheduler.org/&#xff0c;点击Downloads&#xff0c;下载后在目录\docs\dbTables下有常用数据库创建quartz表的脚本&#xff0c;例如&#xff1a;“tables_mysql.sql”table_mysql.sqltable…

【CodeForces - 1062C】Banh-mi (贪心,数学,找规律,快速幂)

题干&#xff1a; JATC loves Banh-mi (a Vietnamese food). His affection for Banh-mi is so much that he always has it for breakfast. This morning, as usual, he buys a Banh-mi and decides to enjoy it in a special way. First, he splits the Banh-mi into nn pa…

【牛客 - 练习】约数个数的和(数论,数学)

题干&#xff1a; 给个n&#xff0c;求1到n的所有数的约数个数的和~ 输入描述: 第一行一个正整数n 输出描述: 输出一个整数&#xff0c;表示答案 示例1 输入 复制 3 输出 复制 5 说明 样例解释&#xff1a; 1有1个约数1 2有2个约数1,2 3有2个约数1,3 备注: n…

mysql json 创建索引_MySQL · 最佳实践 · 如何索引JSON字段

概述MySQL从5.7.8起开始支持JSON字段&#xff0c;这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能&#xff0c;至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能来对JSON对象中的字段…

mysql链路跟踪工具_EasySwoole利用链路追踪组件制作甩锅工具

前言最近前端老是反馈API调用异常&#xff0c;说请求成功但是没有数据返回&#xff01;我写的代码怎么可能有bug&#xff0c;肯定是前端调用的方式不对&#xff01;经过一番套鼓&#xff0c;直接把请求参数和响应内容打印到控制台&#xff0c;果然不出我所料&#xff0c;请求缺…