NC24824. [USACO 2009 Jan G]Safe Travel
描述
By way of example, consider these pastures, cowpaths, and [times]: 1--[2]--2-------+ | | | [2] [1] [3] | | | +-------3--[4]--4 TRAVEL BEST ROUTE BEST TIME LAST PATH p_1 to p_2 1->2 2 1->2 p_1 to p_3 1->3 2 1->3 p_1 to p_4 1->2->4 5 2->4 When gremlins are present: TRAVEL BEST ROUTE BEST TIME AVOID p_1 to p_2 1->3->2 3 1->2 p_1 to p_3 1->2->3 3 1->3 p_1 to p_4 1->3->4 6 2->4 For 20% of the test data, N <= 200. For 50% of the test data, N <= 3000.
输入描述
* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Three space-separated integers:,
, and
输出描述
* Lines 1..N-1: Line i contains the smallest time required to travel fromto
while avoiding the final cowpath of the shortest path from
to
. If no such path exists from
to
, output -1 alone on the line.
示例1
输入:
4 5 1 2 2 1 3 2 3 4 4 3 2 1 2 4 3
输出:
3 3 6
C++14(g++5.4) 解法, 执行用时: 179ms, 内存消耗: 22304K, 提交时间: 2019-09-21 08:53:47
#include<bits/stdc++.h> using namespace std; typedef long long int_t; const int_t maxn = 100010; const int_t inf = 2147483647; int_t dis[maxn],frm[maxn],fa[maxn],ans[maxn]; struct node{ int_t a,b,c; node(int_t a,int_t b,int_t c):a(a),b(b),c(c){} }; struct E{ int_t u,v,w; E(int_t u=0,int_t v=0,int_t w=0):u(u),v(v),w(w){} }Es[maxn<<1]; bool operator <(node a,node c){return a.b > c.b;} priority_queue<node> pque; vector<pair<int_t,int_t> > G[maxn]; void dijkstra(int_t n){ for(int_t i=1;i<=n;i++) dis[i] = inf; pque.push(node(1,0,0)); while(!pque.empty()){ node tp = pque.top();pque.pop(); if(dis[tp.a] != inf) continue; int_t rt = tp.a; dis[rt] = tp.b;frm[rt] = tp.c; for(pair<int_t,int_t> e : G[rt]) if(dis[e.first] == inf) pque.push(node(e.first,e.second + dis[rt],rt)); } } int_t read(){ int_t x = 0,w = 1;char ch = 0; while(!isdigit(ch)) {ch = getchar();if(ch == '-') w = -1;} while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * w; } int_t find(int_t rt){return rt == fa[rt] ? rt : fa[rt] = find(fa[rt]);} int main(){ int_t n = read(),m = read(),tmp=0,ttp=0; while(m--){ int_t u = read(),v = read(), w = read(); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } dijkstra(n); for(int_t i=1;i<=n;i++){ fa[i] = i;ans[i] = inf; for(auto e : G[i]) if(frm[i] != e.first && frm[e.first] != i && e.first > i) Es[++tmp] = E(i,e.first,e.second+dis[i]+dis[e.first]); } sort(Es+1,Es+tmp+1,[](E a,E b){return a.w < b.w;}); for(int_t i=1;i<=tmp && ttp < n-1;i++){ int_t u = Es[i].u,v = Es[i].v,w = Es[i].w; while(find(u) != find(v)){ ++ttp; if(dis[find(u)] < dis[find(v)]) swap(u,v); ans[find(u)] = min(ans[find(u)],w - dis[find(u)]); fa[find(u)] = frm[find(u)]; u = fa[find(u)]; } } for(int_t i=2;i<=n;i++) printf("%lld\n",ans[i] == inf ? -1 : ans[i]); }
C++11(clang++ 3.9) 解法, 执行用时: 106ms, 内存消耗: 10460K, 提交时间: 2019-09-21 09:13:15
#include<bits/stdc++.h> #define in read() #define re register #define ll long long using namespace std; inline int read(){ char ch;int f=1,res=0; while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1; while(ch>='0'&&ch<='9'){ res=(res<<1)+(res<<3)+(ch^48); ch=getchar(); } return f==1?res:-res; } const int N=1e5+10,M=4e5+10; bool vis[N]; int n,m,tfa[N],d[N],fa[N],ans[N]; int nxt[M],head[N],ecnt=0,cnt=0; struct node{int u,v,w;}e[M],tree[M]; inline bool cmp(const node &a,const node &b){return a.w<b.w;} inline void add(int x,int y,int z){ nxt[++ecnt]=head[x];head[x]=ecnt; e[ecnt].u=x;e[ecnt].v=y;e[ecnt].w=z; } inline int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);} inline void dij(){ priority_queue<pair<int,int> > q; memset(d,127/3,sizeof(d)); q.push(make_pair(0,1));d[1]=0; while(!q.empty()){ int u=q.top().second;q.pop(); if(vis[u]) continue; vis[u]=1; for(re int i=head[u];i;i=nxt[i]){ int v=e[i].v; if(d[v]>d[u]+e[i].w){ d[v]=d[u]+e[i].w; tfa[v]=u; q.push(make_pair(-d[v],v)); } } } } int main(){ n=in;m=in; for(re int i=1;i<=m;++i){ int x,y,z; x=in;y=in;z=in; add(x,y,z);add(y,x,z); } dij(); for(re int i=1;i<=2*m;i+=2){//寻找非树边 int u=e[i].u,v=e[i].v; if(tfa[u]==v||tfa[v]==u) continue; tree[++cnt].w=d[u]+e[i].w+d[v]; tree[cnt].u=u; tree[cnt].v=v; } sort(tree+1,tree+cnt+1,cmp); memset(ans,-1,sizeof(ans)); for(re int i=1;i<=n;++i) fa[i]=i; for(re int i=1;i<=cnt;++i){ int u=getfa(tree[i].u),v=getfa(tree[i].v); while(u!=v){//把这条非树边能够更新的都更新 if(d[u]<d[v]) swap(u,v); ans[u]=tree[i].w-d[u]; fa[u]=tfa[u]; u=getfa(u); } } for(re int i=2;i<=n;++i) printf("%d\n",ans[i]); return 0; }