2018.10.29-dtoj-4001-分身术(phantom)
Posted jessie-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018.10.29-dtoj-4001-分身术(phantom)相关的知识,希望对你有一定的参考价值。
题目描述:
题目背景:当您再次回到机房时已经是中午了,于是您决定去吃饭。
从机房到食堂的地图可以简化为一张
n 个点,m 条边的有向图,通过每条边需要一定的时间。机房在1号节点,食堂在n号节点。膜法师hercier 使用结界将食堂和一些点封锁了起来使其无法通过,如果想通过某个节点,你就必须破坏掉维持这个节点结界的所有结界发生器。幸运的是,你在上一题的未知森林里领悟了分身术,你可以分出无限多的分身去破坏结界发生器,normalgod 想知道你最早什么时候能到达食堂,请你写个程序告诉他。(破坏瞬间完成,分身移动速度与本体相同)
输入:
第一行2 个整数,分别表示n,m 。
之后m 行每行三个整数a,b,c 表示a 到b有一条需要走c分钟的边。
之后n行每行一个正整数k kk表示维持这个节点结界的结界发生器数目。
之后k 个1?n 之间的节点编号,表示每个结界发生器的位置。
输出
到达食堂的最早时间,永远不能到达输出?1 。
数据范围:
对于20% 的数据,满足 n≤15,m≤50 n≤15,m≤50n≤15,m≤50
对于50% 的数据,满足 n≤500,m≤6000
对于另20% 的数据,满足k=0对于100% 的数据,满足n≤3000,m≤70000,1≤c≤108
算法标签:dijk&拓扑
思路:
把限制转化拓扑序,每次按照拓扑序入队列,开个数组记录通向这个点的分身所需要的最大值,dijk套拓扑,思路不难要坚定信念吧,不要怀疑自己....
啊...我的题解越来越短越来越失去观赏度了咦...
以下代码:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=3005,M=70005;const LL inf=1e18; int n,m,ne[M],head[N],to[M],w[M],in[N],ne1[M],head1[N],to1[M],cnt; LL d[N],ma[N];bool vis[N],tag[N]; struct node{int x;LL d;bool operator<(const node&t1)const{return d>t1.d;};};priority_queue<node> q; il int read(){int x,f=1;char ch;_(!)ch==‘-‘?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;} il void ins(int x,int y){ne1[++cnt]=head1[x];head1[x]=cnt;to1[cnt]=y;} il void dijk(){ for(int i=1;i<=n;i++)d[i]=inf;d[1]=0;q.push((node){1,0}); while(!q.empty()){ node now=q.top();q.pop(); if(vis[now.x])continue;vis[now.x]=1; for(int i=head1[now.x];i;i=ne1[i]){ ma[to1[i]]=max(d[now.x],ma[to1[i]]); if(--in[to1[i]]==0&&tag[to1[i]]){ d[to1[i]]=max(d[to1[i]],ma[to1[i]]); q.push((node){to1[i],d[to1[i]]}); } } for(int i=head[now.x];i;i=ne[i]){ if(d[to[i]]<d[now.x]+(LL)w[i]&&ma[to[i]]<d[now.x]+(LL)w[i])continue; d[to[i]]=d[now.x]+(LL)w[i];d[to[i]]=max(d[to[i]],ma[to[i]]);tag[to[i]]=1; if(in[to[i]]==0)q.push((node){to[i],d[to[i]]}); } } } int main() { n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); insert(x,y,z); }bool pd=0;cnt=0; for(int i=1;i<=n;i++){ int k=read(); while(k--){ int x=read();if(i==1&&x==1){puts("-1");pd=1;} ins(x,i);in[i]++; } } if(pd)return 0; dijk();if(d[n]==inf){puts("-1");}else printf("%lld ",d[n]); return 0; }
以上是关于2018.10.29-dtoj-4001-分身术(phantom)的主要内容,如果未能解决你的问题,请参考以下文章
scratch分身术 电子学会图形化编程scratch等级考试三级真题和答案解析2021-12
Kubernetes网络自学系列 | 物理网卡的分身术:Macvlan