2016 Multi-university-training-contests-2 1006 点双连通分量
来源:互联网 发布:程序员背包 编辑:程序博客网 时间:2024/06/09 22:37
链接
http://acm.hdu.edu.cn/showproblem.php?pid=5739
题意
给一个有n个节点和m条边的无向图,每个点有自己的点权wi,Gi的定义是删除i点形成的子图。
Gi的权值计算方法为
- 若为连通的图,是每个点的点权的乘积。
- 不连通,每个连通图或者孤立点的和。
最后求
解析
首先我想说说ACM-ICPC程序设计系列 图论及应用。模板代码有坑啊,坑的一手好逼。
接下来,说说思路,根据题意,可以判断主要求点双连通分量,求出割点,将不是割点的点进行缩点。之后就形成了一棵树,在树上面进行计算就方便多了。遍历新图,依次遍历割点、缩点和孤立节点,记录它们整个块的权值。
计算。
1、若为割点,但不是根节点,整个连通块权值除以以他为根的子树的权值,然后在加该及节点的每个子树的权值;若是根节点直接加他的子树的权值。
2、若不是割点,直接整个连通块的权值除以该接点的权值。
注意:除法的取模,用费马小定理。
代码
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 200000+5;const int mod = 1000000000+7;int n, m;vector<int>p[maxn], V[maxn], E[maxn];int w[maxn], iw[maxn];int low[maxn], dfn[maxn];bool flag[maxn], vis[maxn];int st[maxn];int pre[maxn];int stk, sig, bcc_cnt;int color[maxn];int dp[maxn];void init() { memset(dfn, 0, sizeof(dfn)); memset(pre, -1, sizeof(pre)); stk = 0; sig = 0; bcc_cnt = n; memset(flag, false, sizeof(flag)); memset(vis, false, sizeof(vis)); memset(color, 0, sizeof(color));}int pow(int a, int b) { int res = 1; while (b) { if (b&1) res = 1LL*res*a%mod; a = 1LL*a*a%mod; b >>= 1; } return res;}void tarjan(int now, int pre) { dfn[now] = low[now] = ++sig; st[++stk] = now; int son = 0; for (int i=0; i<p[now].size(); i++) { int v = p[now][i]; son++; if (v == pre) continue; if (!dfn[v]) { tarjan(v, now); low[now] = min(low[now], low[v]); if (low[v] >= dfn[now]) { // now不为树根时, low[v] >= dfn[now], 就说明now是割点。 bcc_cnt++; flag[now] = true; w[bcc_cnt] = 1; V[bcc_cnt].clear(); do { w[bcc_cnt] = 1LL*w[bcc_cnt]*w[st[stk]]%mod; V[bcc_cnt].push_back(st[stk]); }while (st[stk--] != v); w[bcc_cnt] = 1LL*w[bcc_cnt]*w[now]%mod; V[bcc_cnt].push_back(now); } } else low[now] = min(low[now], dfn[v]); } if (pre < 0 && son == 1) //now为树根,但是它的子树必须超过一个。 flag[now] = false;}void DFS(int u, int p, int fa) { color[u] = fa; vis[u] = true; pre[u] = p; dp[u] = w[u]; for (int i=0; i<E[u].size(); i++) { int v = E[u][i]; if (v == p) continue; DFS(v, u, fa); dp[u] = 1LL*dp[u]*dp[v]%mod; } if (u > n) { for (int i=0; i<V[u].size(); i++) { vis[V[u][i]] = true; color[V[u][i]] = fa; } }}int main(){ int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); init(); for (int i=1; i<=n; i++) { p[i].clear(); scanf("%d", &w[i]); iw[i] = pow(w[i], mod-2); } for (int i=0; i<m; i++) { int u, v; scanf("%d%d", &u, &v); p[u].push_back(v); p[v].push_back(u); } for (int i=1; i<=n; i++) { if (!dfn[i]) tarjan(i, -1); } for (int i=1; i<=bcc_cnt; i++) E[i].clear(); for (int i=n+1; i<=bcc_cnt; i++) { for (int j=0; j<V[i].size(); j++) { int v = V[i][j]; if (flag[v]) { E[i].push_back(v); E[v].push_back(i); w[i] = 1LL*w[i]*iw[v]%mod; } } } int ans = 0; for (int i=1; i<=n; i++) { //遍历割点 if (!vis[i] && flag[i]) { DFS(i, -1, i); ans = (ans+dp[i])%mod; } } for (int i=n+1; i<=bcc_cnt; i++) { // 遍历没有割点的连通块 if (!vis[i]) { DFS(i, -1, i); ans = (ans+dp[i])%mod; } } for (int i=1; i<=n; i++) { //遍历孤立节点 if (!vis[i]) { DFS(i, -1, i); ans = (ans+dp[i])%mod; } } int res = 0; for (int i=1; i<=n; i++) { int fa = color[i]; int temp = ans; ans = (ans-dp[fa]+mod)%mod; if (flag[i]) { int t = 1LL*dp[fa]*pow(dp[i], mod-2)%mod; if (i != fa) ans = (ans+t)%mod; for (int j=0; j<E[i].size(); j++) { int v = E[i][j]; if (pre[v] == i) ans = (ans + dp[v])%mod; } } else { if (i != fa) ans = (ans+1LL*dp[fa]*iw[i]%mod)%mod; } res = (res + 1LL*i*ans)%mod; ans = temp; } printf("%d\n", res); } return 0;}
0 0
- 2016 Multi-university-training-contests-2 1006 点双连通分量
- 点双连通分量
- 点双连通分量
- 点双连通分量
- 点双连通分量
- 点-双连通分量模板
- 求点双连通分量
- 点-双连通分量&边-双连通分量复习笔记
- POJ 2942 点的双连通分量
- 计算点-双连通分量算法
- poj2942 点双连通分量
- 割点、桥、双连通分量
- 割点 桥 双连通分量模版
- 点/边 双连通分量---Tarjan算法
- POJ1523 SPF【点双连通分量】【Tarjan】
- tarjan求点的双连通分量
- 点的双连通分量问题
- hdu3749 Financial Crisis(点-双连通分量)
- Git命令:将当前目录文件移动到上级目录
- Java 8 数据流教程
- storm消息机制
- java绘图技术
- VIM常用命令
- 2016 Multi-university-training-contests-2 1006 点双连通分量
- 二叉排序树与双向链表的转换
- HDU 4749 Parade Show 数据结构KMP变形
- poj 1932 XYZZY(SPFA)
- HDOJ 5363 Key Set
- Ubuntu 安装百度云客户端
- AngularJS Directive 隔离 Scope 数据交互
- PHP开启curl库的解决方法
- Mirantis OpenStack Fuel9.0离线安装(MOS9.0本地源)