2016多校联合第二场 HDU5739 Fantasia 解题报告
来源:互联网 发布:数据审计追踪 编辑:程序博客网 时间:2024/05/22 00:44
这道题当时赛上过的队比较少读了一遍就没怎么管了。赛后仔细想了想感觉并不是特别难做,tarjan的时候对割点进行处理就行了,写的时候才发现细节巨多堪比模拟。
题目大意:对于一个带点权的图,定义每个连通分量对图权重的贡献为分量里所有点权的乘积,不同分量之间就求和是整个图总权值。又定义zi 为删去i 点后图的权值,求S=(∑ni=1i⋅zi)mod(109+7) 。
思路:先预处理出每个连通分量的权值以及原图的总权值sum ,接下来跑一遍tarjan求割点算法。
如果一个点不是割点直接将其从该连通分量的权值中除去,顺便注意孤立点的处理。
割点则有两种情况:
1. 根节点:统计所有子树的权值和,将该连通分量的权值更新;
2. 非根节点:统计所有满足low[v]≥dfn[u] 子树的权值和与权值积,前者用于对答案的贡献,后者为了计算出父节点所在连通分量的权值。
代码:
#include <set>#include <map>#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1e5 + 15;const int maxm = 1e6 + 15;const int inf = 0x3f3f3f3f;typedef long long ll;const ll mod = 1e9 + 7;struct Edge { int to, next;} edge[maxm];int ecnt, head[maxn];ll quickPow(ll x, ll y) { ll res = 1; while(y) { if(y & 1) res = res * x % mod; y >>= 1; x = x * x % mod; } return res;}ll inv(ll x) { return quickPow(x, mod - 2);}void add(int u, int v) { edge[ecnt].to = v; edge[ecnt].next = head[u]; head[u] = ecnt++;}ll w[maxn], ans[maxn], val[maxn], Sum;int dfn[maxn], low[maxn], cnt, vis[maxn];void init(int n) { Sum = cnt = ecnt = 0; memset(vis, 0, sizeof(int) * (n + 1)); memset(dfn, 0, sizeof(int) * (n + 1)); memset(head, -1, sizeof(int) * (n + 1));}void dfs(int u) { vis[u] = 1; val[u] = w[u]; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if(vis[v]) continue; dfs(v); val[u] = val[u] * val[v] % mod; }}inline void add(ll &x, ll y) { x += y; if(x >= mod) x -= mod;}ll tarjan(int fa, int u, int root) { ll res = w[u], sum = 0, pro = w[u]; dfn[u] = low[u] = ++cnt; int chd = 0, fg = 0; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if(!dfn[v]) { chd++; ll tmp = tarjan(u, v, root); low[u] = min(low[u], low[v]); if(!fa) add(sum, tmp); if(!fa && chd > 1) fg = 1; if(fa && low[v] >= dfn[u]) { add(sum, tmp); pro = pro * tmp % mod; fg = 1; } res = res * tmp % mod; } else if(v != fa) low[u] = min(low[u], dfn[v]); } if(!fg) { // 孤立点 if(!fa and head[u] == -1) {ans[u] = (Sum - val[root] + mod) % mod; } else ans[u] = ((Sum - val[root] + mod) % mod + val[root] * inv(w[u]) % mod) % mod; } else { ll pre = val[root] * inv(pro) % mod; if(fa) add(sum, pre); ans[u] = (Sum - val[root] + mod) % mod; add(ans[u], sum); } return res;}int vec[maxn];inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x;} int main() { int t; scanf("%d", &t); while(t--) { int n = read(), m = read(); init(n); for(int i = 1; i <= n; i++) w[i] = read(); for(int i = 1; i <= m; i++) { int u = read(), v = read(); add(u, v); add(v, u); } int tot = 0; for(int i = 1; i <= n; i++) { if(vis[i]) continue; vec[++tot] = i; dfs(i); add(Sum, val[i]); } for(int i = 1; i <= tot; i++) tarjan(0, vec[i], vec[i]); ll S = 0; for(int i = 1; i <= n; i++) add(S, ans[i] * i % mod); printf("%lld\n", S); } return 0;}
0 0
- 2016多校联合第二场 HDU5739 Fantasia 解题报告
- [HDU5739] Fantasia [2016 Multi-University Training Contest 2(多校联合训练2) F]
- 2016多校联合第二场 HDU5741解题报告
- 2016多校联合第二场 HDU5735 Born Slippy 解题报告
- hdu 5739 Fantasia (2016多校第二场1006)
- 2016多校联合第一场 HDU5731解题报告
- 2013年HDU多校联合第三场解题报告
- HDU 4876 ZCC loves cards (2014多校联合训练第二场1005) 解题报告(暴力+剪枝)
- 2016多校联合第二场
- HDU/杭电2013多校第二场解题报告
- HDU 4864 Task (2014多校联合训练第一场1004) 解题报告(贪心)
- 多校联合 第二场 A
- 多校联合 第二场 E DP
- [HDU3974] 解题报告 && 多校联合反思
- 130725hdu杭电多校第二场解题报告
- bo_jwolf不卖萌的第二场解题报告
- HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)
- 多校第七场解题报告
- VS2010出现“为帮助内容存储区指定的位置无效或者您无权访问该位置”的解决办法
- CollapsingToolbarLayout简单应用
- Introducing Kafka Streams: Stream Processing Made Simple
- Redis的分片、预分片技术总结
- codeforces No to Palindromes!(字符串处理,不能有回文)
- 2016多校联合第二场 HDU5739 Fantasia 解题报告
- java使用ajax实现进度条
- hdoj 1085 Holding Bin-Laden Captive! <思维>
- C++文件的读写
- Informix11.70培训笔记(3)
- 数据库基础知识
- 连载:面向对象葵花宝典:思想、技巧与实践(14) - 面向对象开发技术流程
- Golang1.7使用ICMP协议实现ping功能,带TIME和TTL
- 怎样提高程序员的软实力,走上人生巅峰(http://bbs.jointforce.com/topic/17845?ref=myread)