Wannafly挑战赛2 B 题 Travel 【最短路 + 思维】
2017-10-31 10:36
549 查看
传送门
//题意: 在一个环上, 有许多城市, 告诉相邻城市之间距离. 然后在这些城市中有一些传送门, 连接两座城市和一个距离, 然后给出q次询问, 问两座城市之间的最小距离.
//思路: 本题的关键点在于传送门的数量很少, 只有20座, 然后观察可发现, 一个城市到另一个城市的最短距离要么就是走环上的距离, 要么就是起点通过某一个有传送门的点再到达终点, 所以我们先预处理出所有特殊点到所有点的最短距离, 特殊点不多只有40个, 复杂度是40*n*logn, 然后q询问, 直接暴力枚举40个点和O1的环上距离,即可出答案. 总复杂为(40*n*logn + q*40).
AC Code
//题意: 在一个环上, 有许多城市, 告诉相邻城市之间距离. 然后在这些城市中有一些传送门, 连接两座城市和一个距离, 然后给出q次询问, 问两座城市之间的最小距离.
//思路: 本题的关键点在于传送门的数量很少, 只有20座, 然后观察可发现, 一个城市到另一个城市的最短距离要么就是走环上的距离, 要么就是起点通过某一个有传送门的点再到达终点, 所以我们先预处理出所有特殊点到所有点的最短距离, 特殊点不多只有40个, 复杂度是40*n*logn, 然后q询问, 直接暴力枚举40个点和O1的环上距离,即可出答案. 总复杂为(40*n*logn + q*40).
AC Code
const ll INF = 1e18; const int maxn = 1e5+5; int cas=1; struct node { int to; ll w; int next; bool operator < (const node& a) const { return a.w < w; } }e[maxn<<1]; int cnt,head[maxn]; void add(int u,int v,ll w) { e[cnt ] = (node){v,w,head[u]}; head[u] = cnt++; } bool vis[maxn]; ll dis[50][maxn]; int id[50]; int n,m; void dij(int st) { for(int i=1;i<=n;i++) dis[st][i] = INF; priority_queue<node>q; Fill(vis,0); dis[st][id[st]] = 0; q.push((node){id[st],0,0}); while(!q.empty()){ node u = q.top(); q.pop(); if(vis[u.to]) continue; vis[u.to] = 1; for(int i=head[u.to]; ~i ; i=e[i].next){ node k = e[i]; if(dis[st][k.to] > dis[st][u.to] + k.w){ dis[st][k.to] = dis[st][u.to] + k.w; q.push((node){k.to,dis[st][k.to],0}); } } } } ll sum[maxn],d[maxn]; vector<int>ve; ll tot; void solve() { while(~scanf("%d%d",&n,&m)){ Fill(head,-1); Fill(sum,0); cnt = 0; tot = 0; for(int i=2;i<=n+1;i++) { scanf("%lld",&d[i]); tot += d[i]; if(i==n+1) { add(1,n,d[i]); add(n,1,d[i]); } else{ add(i,i-1,d[i]); add(i-1,i,d[i]); } sum[i] = sum[i-1] + d[i]; } for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); ve.push_back(u); ve.push_back(v); } sort(ve.begin(),ve.end()); ve.erase(unique(ve.begin(),ve.end()),ve.end()); int tt = 0; for(int i=0;i<ve.size();i++){ id[++tt] = ve[i]; dij(tt); } int q; scanf("%d",&q); while(q--){ int u,v; scanf("%d%d",&u,&v); ll ans = min(abs(sum[v] - sum[u]),tot - abs(sum[v] - sum[u])); for(int i=1;i<=tt;i++){ ans = min(ans,dis[i][u] + dis[i][v]); } cout << ans << endl; } } }
相关文章推荐
- Wannafly 挑战赛第二场 B Travel【最短路 建图】
- Wannafly挑战赛2 B.Travel【思维+SPFA】
- Wannafly挑战赛2-B.Travel(最短路)
- 【Wannafly挑战赛2 】B - Travel
- 【Wannafly挑战赛1 】B Xorto 【思维+二分】
- Wannafly挑战赛4-dfs序&线段树|搜索&思维|BIT-树的距离
- Wannafly挑战赛2-B-Travel(floyd+离散化)
- Wannafly挑战赛2 B - Travel (Dijkstra)
- Wannafly挑战赛6-E:双拆分数(思维)
- Wannafly挑战赛6 E 双拆分数【思维】
- Wannafly 挑战赛5 A 题 珂朵莉与宇宙 【思维 + 前缀和】
- Wannafly挑战赛5 A 珂朵莉与宇宙(思维暴力)
- Wannafly挑战赛5 -- A(前缀和) B(思维)
- Wannafly挑战赛1 B.Xorto【思维+二分】
- 【Wannafly挑战赛5】 A 【思维枚举】B C【排列组合 公式】
- Wannafly挑战赛9 C 列一列【思维取模 + 大数】
- Wannafly挑战赛1 B - 思维题
- Wannafly挑战赛3-C.位数差(思维)
- wannafly挑战赛4C-水题&思维-割草机
- Wannafly挑战赛5 A珂朵莉与宇宙(思维)