1. 程式人生 > >2018.10.29-dtoj-4001-分身術(phantom)

2018.10.29-dtoj-4001-分身術(phantom)

getchar div \n none void orm 輸出 put prior

題目描述:

題目背景:當您再次回到機房時已經是中午了,於是您決定去吃飯。

從機房到食堂的地圖可以簡化為一張
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\n",d[n]); return 0; }
View Code

2018.10.29-dtoj-4001-分身術(phantom)