记录编号 138067 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2012]飞行计划 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.843 s
提交时间 2014-11-05 17:00:01 内存使用 3.93 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<vector>
  7. #include<queue>
  8. using namespace std;
  9. const int SIZEN=2010,SIZEM=10010,SIZEGN=220010,INF=0x7fffffff/2;
  10. int GN;//0~N-1
  11. vector<pair<int,int> > c[SIZEGN];
  12. int f[SIZEGN];
  13. bool inq[SIZEGN];
  14. queue<int> Q;
  15. void addedge(int a,int b,int w){
  16. c[a].push_back(make_pair(b,w));
  17. }
  18. int SPFA(int S,int T){
  19. for(int i=0;i<GN;i++) f[i]=INF;
  20. memset(inq,0,sizeof(inq));
  21. while(!Q.empty()) Q.pop();
  22. f[S]=0;inq[S]=true;Q.push(S);
  23. while(!Q.empty()){
  24. int x=Q.front();Q.pop();inq[x]=false;
  25. for(int i=0;i<c[x].size();i++){
  26. int u=c[x][i].first;
  27. if(f[x]+c[x][i].second<f[u]){
  28. f[u]=f[x]+c[x][i].second;
  29. if(!inq[u]){
  30. inq[u]=true;
  31. Q.push(u);
  32. }
  33. }
  34. }
  35. }
  36. return f[T];
  37. }
  38. int N,M,C;
  39. class EDGE{
  40. public:
  41. int u,v,h,w;
  42. int l,r;
  43. };
  44. EDGE edges[SIZEM];
  45. vector<int> legal[SIZEN];
  46. int sum[SIZEN];
  47. void unique(vector<int> &s){
  48. sort(s.begin(),s.end());
  49. int tot=0;
  50. for(int i=0;i<s.size();i++){
  51. if(!i||s[i]!=s[i-1]) s[tot++]=s[i];
  52. }
  53. while(s.size()>tot) s.pop_back();
  54. }
  55. void mark_legal_height(void){//计算每个节点的合法高度
  56. legal[0].push_back(0);
  57. legal[N-1].push_back(0);
  58. for(int i=0;i<M;i++){
  59. edges[i].l=edges[i].h-(C/2),edges[i].r=edges[i].h+(C/2);
  60. edges[i].l=max(edges[i].l,0);
  61. for(int j=edges[i].l;j<=edges[i].r;j++){
  62. legal[edges[i].u].push_back(j);
  63. legal[edges[i].v].push_back(j);
  64. }
  65. }
  66. for(int i=0;i<N;i++) unique(legal[i]);
  67. sum[0]=0;
  68. for(int i=1;i<N;i++) sum[i]=sum[i-1]+legal[i-1].size();
  69. }
  70. int hash1(int i,int j){//i处的第j个合法高度
  71. return sum[i]+j;
  72. }
  73. int hash2(int i,int h){//i处高度为h
  74. return sum[i]+lower_bound(legal[i].begin(),legal[i].end(),h)-legal[i].begin();
  75. }
  76. void makegraph(void){
  77. GN=sum[N-1]+legal[N-1].size();
  78. for(int i=0;i<N;i++){
  79. for(int j=0;j+1<legal[i].size();j++){
  80. //爬升有花费,下降没有
  81. addedge(hash1(i,j),hash1(i,j+1),(legal[i][j+1]-legal[i][j])*C);
  82. addedge(hash1(i,j+1),hash1(i,j),0);
  83. }
  84. }
  85. for(int i=0;i<M;i++){
  86. for(int j=edges[i].l;j<=edges[i].r;j++){
  87. int a=hash2(edges[i].u,j),b=hash2(edges[i].v,j);
  88. int w=(edges[i].h-j)*(edges[i].h-j)+edges[i].w;
  89. addedge(a,b,w);
  90. addedge(b,a,w);
  91. }
  92. }
  93. }
  94. void read(void){
  95. scanf("%d%d%d",&N,&M,&C);
  96. for(int i=0;i<M;i++){
  97. scanf("%d%d%d%d",&edges[i].u,&edges[i].v,&edges[i].h,&edges[i].w);
  98. }
  99. }
  100. int main(){
  101. freopen("nt2012_route.in","r",stdin);
  102. freopen("nt2012_route.out","w",stdout);
  103. read();
  104. mark_legal_height();
  105. makegraph();
  106. printf("%d\n",SPFA(hash1(0,0),hash2(N-1,0)));
  107. return 0;
  108. }