[USACO09JAN]安全出行Safe Travel
题目描述
Gremlins have infested the farm. These nasty, ugly fairy-like
creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 to pasture_i. Each gremlin is personalized and knows the quickest path that cow_i normally takes to pasture_i. Gremlin_i waits for cow_i in the middle of the final cowpath of the quickest route to pasture_i, hoping to harass cow_i.
Each of the cows, of course, wishes not to be harassed and thus chooses an at least slightly different route from pasture_1 (the barn) to pasture_i.
Compute the best time to traverse each of these new not-quite-quickest routes that enable each cow_i that avoid gremlin_i who is located on the final cowpath of the quickest route from pasture_1 to
pasture_i.
As usual, the M (2 <= M <= 200,000) cowpaths conveniently numbered 1..M are bidirectional and enable travel to all N (3 <= N <= 100,000) pastures conveniently numbered 1..N. Cowpath i connects pastures a_i (1 <= a_i <= N) and b_i (1 <= b_i <= N) and requires t_i (1 <= t_i <= 1,000) time to traverse. No two cowpaths connect the same two pastures, and no path connects a pasture to itself (a_i != b_i). Best of all, the shortest path regularly taken by cow_i from pasture_1 to pasture_i is unique in all the test data supplied to your program.
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.
TIME LIMIT: 3 Seconds
MEMORY LIMIT: 64 MB
Gremlins最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的 地是牛棚_i).每一个gremlin只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经.所以它 们在牛_i到牛棚_i之前的最后一条牛路上等牛_i. 当然,牛不愿意遇到Gremlins,所以准备找 一条稍微不同的路经从牛棚_1走到牛棚_i.所以,请你为每一头牛_i找出避免gremlin_i的最 短路经的长度. 和以往一样, 农场上的M (2 <= M <= 200,000)条双向牛路编号为1..M并且能让所有牛到 达它们的目的地, N(3 <= N <= 100,000)个编号为1..N的牛棚.牛路i连接牛棚a_i (1 <= a_i <= N)和b_i (1 <= b_i <= N)并且需要时间t_i (1 <=t_i <= 1,000)通过. 没有两条牛路连接同样的牛棚,所有牛路满足a_i!=b_i.在所有数据中,牛_i使用的牛棚_1到牛 棚_i的最短路经是唯一的.
输入输出格式
输入格式:
-
Line 1: Two space-separated integers: N and M
- Lines 2..M+1: Three space-separated integers: a_i, b_i, and t_i
输出格式:
- Lines 1..N-1: Line i contains the smallest time required to travel from pasture_1 to pasture_i+1 while avoiding the final cowpath of the shortest path from pasture_1 to pasture_i+1. If no such path exists from pasture_1 to pasture_i+1, output -1 alone on the line.
输入输出样例
4 5 1 2 2 1 3 2 3 4 4 3 2 1 2 4 3
3 3 6
先构出最短路径树(题目说唯一)
对于一个非树边(u,v) 一定使树构成一个环
并且使环上的点(除了lca(u,v))都有了一个次短路
对于点i 这个所谓次短路的长度就是dist[u]+dist[v]+value[u,v]-dist[i]
可以发现次短路大小长度跟u,v有关 跟i无关
所以对于一个非树边(u,v)设它的权值为dist[u]+dist[v]+value[u,v]
把这个权值按从小到大排序 每次把环上没被赋值过的点赋上值
快速实现上面那个 可以用并查集
1 #include <queue> 2 #include <cstdio> 3 #include <ctype.h> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int MAXN=100010; 9 10 int n,m; 11 12 struct node { 13 int to; 14 int next; 15 int val; 16 }; 17 node e[MAXN*10]; 18 19 struct othertree{ 20 int u,v; 21 int val; 22 bool operator < (const othertree &h) const { 23 return val<h.val; 24 } 25 }; 26 othertree tr[MAXN*5]; 27 28 struct fuck { 29 int to,cost; 30 fuck(int a,int b): to(a),cost(b) {} 31 bool operator < (const fuck&k) const { 32 return cost>k.cost; 33 } 34 }; 35 36 int head[MAXN],tot,inr; 37 38 int dis[MAXN],dep[MAXN],fa[MAXN],Id[MAXN],ans[MAXN],da[MAXN]; 39 40 bool vis[MAXN],inthetree[MAXN<<1]; 41 42 priority_queue<fuck> q; 43 44 inline void add(int x,int y,int z) { 45 e[++tot].to=y; 46 e[tot].val=z; 47 e[tot].next=head[x]; 48 head[x]=tot; 49 } 50 51 inline void read(int&x) { 52 int f=1;register char c=getchar(); 53 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 54 for(;isdigit(c);x=x*10+c-48,c=getchar()); 55 x=x*f; 56 } 57 58 inline void dij() { 59 q.push(fuck(1,0)); 60 for(int i=1;i<=n;++i) dis[i]=1e9+1e9; 61 dis[1]=0;dep[1]=1; 62 while(!q.empty()) { 63 while(!q.empty()&&vis[q.top().to]) q.pop(); 64 fuck p=q.top(); 65 if(vis[p.to]) continue; 66 vis[p.to]=true; 67 for(int i=head[p.to];i;i=e[i].next) { 68 int to=e[i].to; 69 if(dis[to]>dis[p.to]+e[i].val&&!vis[to]) { 70 dis[to]=dis[p.to]+e[i].val; 71 fa[to]=p.to; 72 dep[to]=dep[p.to]+1; 73 q.push(fuck(to,dis[to])); 74 } 75 } 76 } 77 return; 78 } 79 80 inline void swap(int&a,int&b) { 81 int t=a;a=b;b=t; 82 return; 83 } 84 85 inline int find(int x) { 86 return da[x]==x?x:da[x]=find(da[x]); 87 } 88 89 inline void Ask_ans(int x,int y,int v) { 90 int lastx=-1,lasty=-1; 91 while(find(x)!=find(y)) { 92 if(dep[find(x)]<dep[find(y)]) swap(x,y),swap(lastx,lasty); 93 if(ans[x]==-1) { 94 ans[x]=v-dis[x]; 95 if(lastx!=-1) da[lastx]=x; 96 } 97 else if(lastx!=-1) 98 da[lastx]=find(x); 99 lastx=find(x); 100 x=fa[lastx]; 101 } 102 return; 103 } 104 105 int hh() { 106 freopen("travel.in","r",stdin); 107 freopen("travel.out","w",stdout); 108 int x,y,z; 109 read(n);read(m); 110 for(int i=1;i<=m;++i) 111 read(x),read(y),read(z),add(x,y,z),add(y,x,z); 112 dij(); 113 for(int i=1;i<=n;++i) 114 for(int j=head[i];j;j=e[j].next){ 115 int to=e[j].to; 116 if(fa[to]==i||fa[i]==to) continue; 117 tr[inr].u=i;tr[inr].v=to; 118 tr[inr].val=e[j].val+dis[i]+dis[to]; 119 ++inr; 120 } 121 sort(tr,tr+inr); 122 for(int i=1;i<=n;++i) da[i]=i,ans[i]=-1; 123 for(int i=0;i<inr;++i) 124 Ask_ans(tr[i].u,tr[i].v,tr[i].val); 125 for(int i=2;i<=n;++i) printf("%d ",ans[i]); 126 return 0; 127 } 128 129 int sb=hh(); 130 int main() {;}