CSU 2005 Nearest Maintenance Point

以你之姓@ 2022-05-08 11:26 139阅读 0赞

题目:点击打开链接

题意:给一个n个节点m条边的带权无向图,给出s个援助节点,有q个询问,每次问一个节点周边最短距离的援助节点有哪些。

分析:多源点最短路,最短路的变形,使用堆优化的dijkstra算法,把s个援助节点当起点(假设有一个超级原点,和s个援助节点有距离为0的边,就化简成了单源最短路模型),搜到所有节点的最短路,用bitset的位运算传递状态,如果有多个起点的某个节点的最短距离相同,那么这个节点周围最近的援助点就是那多个起点,并且用或运算保存,如果只有一个起点到某个节点的距离最短,那么该节点最近的援助节点就是那个节点,直接赋值传递状态。时间复杂度为O(n*lg(n) + 2*E)。

代码:

  1. #pragma comment(linker, "/STACK:102400000,102400000")
  2. #include<unordered_map>
  3. #include<unordered_set>
  4. #include<algorithm>
  5. #include<iostream>
  6. #include<fstream>
  7. #include<complex>
  8. #include<cstdlib>
  9. #include<cstring>
  10. #include<cassert>
  11. #include<iomanip>
  12. #include<string>
  13. #include<cstdio>
  14. #include<bitset>
  15. #include<vector>
  16. #include<cctype>
  17. #include<cmath>
  18. #include<ctime>
  19. #include<stack>
  20. #include<queue>
  21. #include<deque>
  22. #include<list>
  23. #include<set>
  24. #include<map>
  25. using namespace std;
  26. #define pt(a) cout<<a<<endl
  27. #define debug test
  28. #define mst(ss,b) memset((ss),(b),sizeof(ss))
  29. #define rep(i,a,n) for (int i=a;i<=n;i++)
  30. #define per(i,a,n) for (int i=n-1;i>=a;i--)
  31. #define pii pair<int,int>
  32. #define fi first
  33. #define se second
  34. #define ll long long
  35. #define ull unsigned long long
  36. #define pb push_back
  37. #define mp make_pair
  38. #define inf 0x3f3f3f3f
  39. #define eps 1e-10
  40. #define PI acos(-1.0)
  41. const ll mod = 1e9+7;
  42. const int N = 1e4+10;
  43. ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
  44. int to[4][2]={
  45. {-1,0},{1,0},{0,-1},{0,1}};
  46. int n,m,s,q,d[N],a[N],ans[N];
  47. struct eg{
  48. int to,len;
  49. };
  50. vector<eg> g[N];
  51. bitset<1010> bt[N];
  52. void dij() {
  53. mst(d,inf);
  54. priority_queue<pii,vector<pii>,greater<pii> > pq;
  55. for(int i=1;i<=s;i++) {
  56. d[a[i]]=0;
  57. bt[a[i]][i]=1;
  58. pq.push({0,a[i]});
  59. }
  60. while(!pq.empty()) {
  61. pii tp=pq.top(); pq.pop();
  62. int u=tp.se;
  63. if(d[u]!=tp.fi) continue;
  64. for(int i=0;i<g[u].size();i++) {
  65. eg v=g[u][i];
  66. if(d[u]+v.len<d[v.to]) {
  67. d[v.to]=d[u]+v.len;
  68. pq.push({d[v.to],v.to});
  69. bt[v.to]=bt[u];///直接传递
  70. }else if(d[u]+v.len==d[v.to]) bt[v.to]|=bt[u];///或运算保留多个距离特殊点相同的点
  71. }
  72. }
  73. }
  74. int main() {
  75. ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  76. while(cin>>n>>m>>s>>q) {
  77. for(int i=1;i<=n;i++) g[i].clear(),bt[i].reset();
  78. for(int i=1;i<=m;i++) {
  79. int a,b,c;
  80. cin>>a>>b>>c;
  81. g[a].pb({b,c});
  82. g[b].pb({a,c});
  83. }
  84. for(int i=1;i<=s;i++) cin>>a[i];
  85. sort(a+1,a+s+1);
  86. dij();
  87. while(q--) {
  88. int tot=0,u;
  89. cin>>u;
  90. for(int i=1;i<=s;i++) if(bt[u][i]) ans[++tot]=a[i];
  91. for(int i=1;i<tot;i++) cout<<ans[i]<<" ";
  92. cout<<ans[tot]<<endl;
  93. }
  94. }
  95. return 0;
  96. }

发表评论

表情:
评论列表 (有 0 条评论,139人围观)

还没有评论,来说两句吧...

相关阅读

    相关 csu----报数游戏

    Description n个人站成一行玩一个报数游戏。所有人从左到右编号为1到n。游戏开始时,最左边的人报1,他右边的人报2,编号为3的人报3,等等。当编号为n的人(即最

    相关 CSU 2167

    题意:初始有n\m的点,矩形排列。有2种操作,第一种是将第i行的所有点联通(a<=i<=b),第二种是将第i列的所有点联通(a<=i<=b)。每次操作后输出有多少个联通块。