HDU 5385 The path

待我称王封你为后i 2022-08-04 00:47 123阅读 0赞

如果我们知道每个点的dis值和最短路径树的话,方案是很容易构造的

我们可以采取贪心做法,一开始将1号点作为最短路径树的根,然后左边从2开始,右边从n开始,只要之前加入的点有边连向他们就加入

这样一个点加入的时间就是他的dis值,最短路径树上的父亲也可以确定,于是输出时非树边长度为n,树边长度为两个端点dis之差。

  1. // whn6325689
  2. // Mr.Phoebe
  3. // http://blog.csdn.net/u013007900
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <cstring>
  8. #include <climits>
  9. #include <complex>
  10. #include <fstream>
  11. #include <cassert>
  12. #include <cstdio>
  13. #include <bitset>
  14. #include <vector>
  15. #include <deque>
  16. #include <queue>
  17. #include <stack>
  18. #include <ctime>
  19. #include <set>
  20. #include <map>
  21. #include <cmath>
  22. #include <functional>
  23. #include <numeric>
  24. #pragma comment(linker, "/STACK:1024000000,1024000000")
  25. using namespace std;
  26. #define eps 1e-9
  27. #define PI acos(-1.0)
  28. #define INF 0x3f3f3f3f
  29. #define LLINF 1LL<<62
  30. #define speed std::ios::sync_with_stdio(false);
  31. typedef long long ll;
  32. typedef unsigned long long ull;
  33. typedef long double ld;
  34. typedef pair<ll, ll> pll;
  35. typedef complex<ld> point;
  36. typedef pair<int, int> pii;
  37. typedef pair<pii, int> piii;
  38. typedef vector<int> vi;
  39. #define CLR(x,y) memset(x,y,sizeof(x))
  40. #define CPY(x,y) memcpy(x,y,sizeof(x))
  41. #define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
  42. #define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))
  43. #define mp(x,y) make_pair(x,y)
  44. #define pb(x) push_back(x)
  45. #define lowbit(x) (x&(-x))
  46. #define MID(x,y) (x+((y-x)>>1))
  47. template<class T>
  48. inline bool read(T &n)
  49. {
  50. T x = 0, tmp = 1;
  51. char c = getchar();
  52. while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
  53. if(c == EOF) return false;
  54. if(c == '-') c = getchar(), tmp = -1;
  55. while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
  56. n = x*tmp;
  57. return true;
  58. }
  59. template <class T>
  60. inline void write(T n)
  61. {
  62. if(n < 0)
  63. {
  64. putchar('-');
  65. n = -n;
  66. }
  67. int len = 0,data[20];
  68. while(n)
  69. {
  70. data[len++] = n%10;
  71. n /= 10;
  72. }
  73. if(!len) data[len++] = 0;
  74. while(len--) putchar(data[len]+48);
  75. }
  76. //-----------------------------------
  77. const int MAXN=100010;
  78. set<int> st;
  79. int n,m;
  80. int vis[MAXN],cost[MAXN];
  81. struct Edge
  82. {
  83. int to,next;
  84. }e[MAXN<<1];
  85. int head[MAXN],tot;
  86. int fa[MAXN],dis[MAXN],idx[MAXN];
  87. void init()
  88. {
  89. CLR(fa,-1);CLR(head,-1);
  90. CLR(vis,0);CLR(cost,0);
  91. tot=0;st.clear();
  92. }
  93. void addedge(int u,int v)
  94. {
  95. e[tot].next=head[u];
  96. e[tot].to=v;
  97. head[u]=tot++;
  98. }
  99. int main()
  100. {
  101. int T;
  102. read(T);
  103. while(T--)
  104. {
  105. init();
  106. read(n),read(m);
  107. for(int i=0,u,v;i<m;i++)
  108. {
  109. read(u),read(v);
  110. addedge(u,v);
  111. }
  112. int cnt=1;
  113. int now=1,l=1,r=n,v;
  114. fa[1]=1;dis[1]=0;
  115. while(cnt<n)
  116. {
  117. for(int i=head[now];~i;i=e[i].next)
  118. {
  119. v=e[i].to;
  120. if(fa[v]!=-1 || st.find(v)!=st.end()) continue;
  121. fa[v]=now;idx[v]=i;
  122. st.insert(v);
  123. }
  124. //cout<<" :"<<now<<endl;
  125. cnt++;
  126. int be=*st.begin();
  127. if(be==l+1)
  128. {
  129. cost[idx[be]]=cnt-dis[fa[be]]-1;
  130. dis[be]=cnt-1;
  131. vis[idx[be]]=true;
  132. st.erase(be);
  133. l=now=be;
  134. //cout<<"1:"<<be<<endl;
  135. }
  136. else
  137. {
  138. be=*(st.rbegin());
  139. cost[idx[be]]=cnt-dis[fa[be]]-1;
  140. dis[be]=cnt-1;
  141. vis[idx[be]]=true;
  142. st.erase(be);
  143. now=be;
  144. //cout<<"2:"<<be<<endl;
  145. }
  146. }
  147. for(int i=0;i<m;i++)
  148. if(!vis[i])
  149. printf("%d\n",n);
  150. else
  151. printf("%d\n",cost[i]);
  152. }
  153. return 0;
  154. }

换一种姿势,总体思路差不多

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<iostream>
  5. #include<vector>
  6. #include<set>
  7. #define maxn 100008
  8. using namespace std;
  9. struct yyy
  10. {
  11. int x,m;
  12. };
  13. int ans[maxn];
  14. vector<yyy> g[maxn];
  15. set<int> s;
  16. int vis[maxn];
  17. int pre[maxn];
  18. int prej[maxn];
  19. int main()
  20. {
  21. int T;
  22. int n,m,i;
  23. scanf("%d",&T);
  24. while (T--)
  25. {
  26. scanf("%d%d",&n,&m);
  27. for (i = 1 ; i <= n ; i++)
  28. {
  29. g[i].clear();
  30. vis[i] = -1;
  31. pre[i] = 0;
  32. prej[i] = 0;
  33. }
  34. int x,y,cnt = 0;
  35. for (i = 1 ; i <= m ; i++)
  36. {
  37. ans[i] = n;
  38. scanf("%d%d",&x,&y);
  39. g[x].push_back( (yyy) {y,++cnt} );
  40. }
  41. int l = 1,r = n;
  42. int v;
  43. s.clear();
  44. s.insert(1);
  45. vis[1] = 0;
  46. int dis = -1;
  47. while ( !s.empty() )
  48. {
  49. int L = *s.begin(),R = *(--s.end());
  50. // cout<<L<<' '<<R<<endl;
  51. if (L == l)
  52. x = L,l++;
  53. else x = R,r--;
  54. s.erase(x);
  55. dis++;
  56. if (x != 1)
  57. {
  58. ans[pre[x]] = dis - vis[prej[x]];
  59. vis[x] = dis;
  60. }
  61. for (i = 0 ; i < g[x].size() ; i++)
  62. {
  63. v = g[x][i].x;
  64. if ( vis[v] == -1 )
  65. {
  66. vis[v] = 0;
  67. pre[v] = g[x][i].m;
  68. prej[v] = x;
  69. s.insert(v);
  70. }
  71. }
  72. }
  73. for (i = 1 ; i <= m ; i++)
  74. printf("%d ",ans[i]);
  75. printf("\n");
  76. }
  77. return 0;
  78. }

发表评论

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

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

相关阅读

    相关 2019ccpc网络赛hdu6705 path

    path [题目传送门][Link 1] 解题思路 先用vector存图,然后将每个vector按照边的权值从小到大排序。将每个顶点作为起点的边里最短的边存入优先

    相关 HDU 5385 The path

    如果我们知道每个点的dis值和最短路径树的话,方案是很容易构造的 我们可以采取贪心做法,一开始将1号点作为最短路径树的根,然后左边从2开始,右边从n开始,只要之前加入的点有边

    相关 HDU-4315 Climbing the Hill

    [题目链接][Link 1] 先回到阶梯博弈的裸题中,比如POJ-1704,所有的块只能向左移并且不能跨越,这个向左移的结果我们可以理解为将左边的宽度减少使得右边的宽度增加