2016 World Final F Longest Rivers

来源:互联网 发布:大卫杜夫 知乎 编辑:程序博客网 时间:2024/06/05 20:50

题意:

有n个河流@#¥……()……)——

思路:


考虑河流i,让他尽量排在最前的话,肯定是他直接走到根,对于其他的叶子节点,如果他比河流i短的话,他可以向上覆盖一定的边。所以,还有一些边是没有被覆盖的, 对这些边做一颗生成树,那么比这个河流长的河流个数就是1 + sum {deg[i] - 1}。因此,可以按照dep从大到小来考虑每一个河流,同时,一些边会在某些时刻加到生成树里面,维护1 +sum { deg[i] - 1 }就行了。

#include <bits/stdc++.h>using namespace std;#define LL long long#define pii pair<int, int>#define MP make_pair#define mod 1000000007#define eps 1e-12#define Pi acos(-1.0)#define N 1000020#define M 2000020#define PB push_back#define MP make_pair#define fi first#define se secondconst LL inf = 1LL << 60;int fst[N], nxt[M], vv[M], cost[M], e;void init() {memset(fst, -1, sizeof fst);e = 0;}void add(int u, int v, int c) {vv[e] = v, cost[e] = c, nxt[e] = fst[u], fst[u] = e++;}int n, m, fa[N], bt[N];LL dis[N], midis[N];pair<LL, int> id[N];vector<int> g[N];bool vis[N];string name[N];char s[100];int ans[N];int tot;int deg[N];void dfs(int u, int p) {fa[u] = p;midis[u] = inf;for(int i = fst[u]; ~i; i = nxt[i]) {int v = vv[i];dis[v] = dis[u] + cost[i];bt[v] = cost[i];dfs(v, u);midis[u] = min(midis[u], cost[i] + midis[v]);}if(midis[u] == inf) midis[u] = 0;}void add_it(int u) {if(vis[u]) return;vis[u] = 1;int p = fa[u];deg[p]++;if(tot == 0) tot++;elseif(deg[p] > 1) tot++;add_it(p);}int main() {init();scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++i) {int p, c;scanf("%s%d%d", s, &p, &c);add(p + 1 + n, i, c);name[i] = s;}for(int i = 1; i <= m; ++i) {int p, c;scanf("%d%d", &p, &c);add(p + 1 + n, i + n + 1, c);}dfs(n + 1, 0);for(int i = 1; i <= n; ++i) id[i] = MP(dis[i], i);sort(id + 1, id + n + 1);for(int i = 1; i <= n + m + 1; ++i) {if(i == n + 1) continue;LL t = midis[i] + bt[i];int p = lower_bound(id + 1, id + n + 1, MP(t, -1)) - id;g[p].PB(i);if(p > n) {vector<int> gg;gg[1] = -1;}}tot = 0;vis[n + 1] = 1;for(int i = n; i >= 1; --i) {int u = id[i].se;ans[u] = tot;for(auto v: g[i]) {add_it(v);}}for(int i = 1; i <= n; ++i) printf("%s %d\n", name[i].c_str(), ans[i] + 1);return 0;}


0 0
原创粉丝点击