BZOJ 4016: [FJOI2014]最短路径树问题

 

建最短路树的时候,优先队列加一条限制,当花费相同的时候id小的排前面

这样建出来的最短路树就是符合题意的

 

再考虑点分治

因为不满足前缀加减性,那么考虑按序遍历即可

 

考虑如何同时维护最大值及其个数

判断当前值是大于还是等于已经存的值

如果大于 替换掉,次数置为1

如果等于 次数++

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define INF 0x3f3f3f3f
  5 #define N 60010
  6 #define pii pair <int, int>
  7 int n, m, k;
  8 struct Graph
  9 {
 10     struct node
 11     {
 12         int to, nx, w;
 13         node() {}
 14         node(int to, int nx, int w) : to(to), nx(nx), w(w) {}
 15     }a[N << 1];
 16     int head[N], pos;
 17     void init()
 18     {
 19         memset(head, 0, sizeof head);
 20         pos = 0;
 21     }
 22     void add(int u, int v, int w)
 23     {
 24         a[++pos] = node(v, head[u], w); head[u] = pos;
 25         a[++pos] = node(u, head[v], w); head[v] = pos;
 26     }
 27 }G[2];
 28 #define erp(G, u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w)
 29 
 30 struct node
 31 {
 32     int u, w, fa, v;
 33     node() {}
 34     node(int u, int w, int fa, int v) : u(u), w(w), fa(fa), v(v) {}
 35     bool operator < (const node &other) const
 36     {
 37         if (w != other.w) return w > other.w;
 38         return u > other.u; 
 39     }
 40 };
 41 int dist[N], used[N];
 42 void Dijkstra()
 43 {
 44     for (int i = 1; i <= n; ++i) dist[i] = INF, used[i] = false;
 45     dist[1] = 0; priority_queue <node> q; q.push(node(1, 0, -1, 0));
 46     while (!q.empty())
 47     {
 48         int u = q.top().u;
 49         if (used[u])
 50         {
 51             q.pop();
 52             continue;
 53         }
 54         if (u != 1)
 55             G[1].add(q.top().fa, u, q.top().v);
 56         q.pop();
 57         used[u] = true;
 58         erp(G[0], u) if (!used[v] && dist[v] > dist[u] + w)
 59         {
 60             dist[v] = dist[u] + w;
 61             q.push(node(v, dist[v], u, w));
 62         }
 63     }
 64 }
 65 
 66 int vis[N];
 67 int sum, root, sze[N], f[N];
 68 void getroot(int u, int fa)
 69 {
 70     f[u] = 0, sze[u] = 1;
 71     erp(G[1], u) if (v != fa && !vis[v])
 72     {
 73         getroot(v, u);
 74         sze[u] += sze[v];
 75         f[u] = max(f[u], sze[v]);
 76     }
 77     f[u] = max(f[u], sum - sze[u]);
 78     if (f[u] < f[root]) root = u;
 79 }  
 80 
 81 int deep[N], res[2]; pii t[N]; 
 82 void getdeep(int u, int fa)
 83 {
 84     if (deep[u] <= k)
 85     {
 86         int tmp = dist[u] + t[k - deep[u] + 1].first;
 87         if (tmp == res[0]) res[1] += t[k - deep[u] + 1].second;
 88         else if (tmp > res[0]) res[0] = tmp, res[1] = 1;
 89     }
 90     erp(G[1], u) if (v != fa && !vis[v])
 91     {
 92         deep[v] = deep[u] + 1;
 93         dist[v] = dist[u] + w;
 94         getdeep(v, u);
 95     }
 96 }
 97 
 98 void add(int u, int fa, int flag)
 99 {
100     if (deep[u] <= k)
101     {
102         if (flag)
103         {
104             if (dist[u] == t[deep[u]].first) ++t[deep[u]].second;
105             else if (dist[u] > t[deep[u]].first) t[deep[u]] = pii(dist[u], 1);
106         }
107         else t[deep[u]] = pii(0, 0);
108     }
109     erp(G[1], u) if (v != fa && !vis[v])
110         add(v, u, flag);
111 }
112 
113 void solve(int u) 
114 {
115     vis[u] = 1;
116     t[1] = pii(0, 1);
117     erp(G[1], u) if (!vis[v]) 
118     {
119         deep[v] = 2, dist[v] = w;   
120         getdeep(v, u); add(v, u, 1);  
121     }
122     erp(G[1], u) if (!vis[v])
123         add(v, u, 0);  
124     erp(G[1], u) if (!vis[v])
125     {
126         sum = f[0] = sze[v]; root = 0;
127         getroot(v, 0);
128         solve(root);
129     }
130 }
131 
132 void Run()
133 {
134     while (scanf("%d%d%d", &n, &m, &k) != EOF) 
135     {
136         G[0].init(); G[1].init();
137         memset(res, 0, sizeof res);
138         memset(vis, 0, sizeof vis);
139         for (int i = 1, u, v, w; i <= m; ++i)
140         {
141             scanf("%d%d%d", &u, &v, &w);
142             G[0].add(u, v, w);
143         }
144         Dijkstra();
145         sum = f[0] = n; root = 0;
146         getroot(1, 0); 
147         solve(root);
148         printf("%d %d\n", res[0], res[1]); 
149     }
150 }
151 
152 int main()
153 {
154     #ifdef LOCAL
155         freopen("Test.in", "r", stdin);
156     #endif 
157 
158     Run();
159     return 0;
160 }
View Code

 

posted @ 2019-01-17 21:07  Dup4  阅读(141)  评论(0编辑  收藏  举报