HDU5739 Fantasia

题意:

给出一张\(N\)个点的无向图\(G\),每个点都有权值\(w_i\),要求计算\(\sum_{i=1}^{N}i\cdot G_i % 1e9+7\)

其中\(G_i\)为删掉点\(i\)之后剩下各连通块内点权乘积之和

题解:

显然对于不是割点的点很容易计算出答案

对于割点,我们需要知道删掉这个点之后产生的新的连通块的点权乘积和

\(tarjan\)过程中可以直接处理出各联通子图的点权乘积(除了父节点所在的子图)

而父节点所在子图的点权乘积可以用整张图的点权乘积去除掉除它以外的点的点权乘积

具体实现看代码

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const int MAXN = 2e5+7;
const LL MOD = 1e9+7;
int n,m,bccid[MAXN],dfn[MAXN],low[MAXN],ID,w[MAXN],bel[MAXN],idx;
vector<int> G[MAXN],pt[MAXN];
LL tot,ans,f[MAXN],gw[MAXN],mul[MAXN],subsum[MAXN],submul[MAXN];
bool iscut[MAXN];
LL ksm(LL a, LL b){
LL ret = 1;
while(b){
if(b&1) ret = ret * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ret;
}
LL inv(LL x){ return ksm(x,MOD-2); }
void init(){
for(int i = 1; i <= n; i++) G[i].clear();
memset(dfn+1,0,n<<2);
memset(bel+1,0,n<<2);
memset(iscut+1,0,n);
fill(submul+1,submul+1+n,1);
fill(subsum+1,subsum+1+n,0);
ans = tot = ID = idx = 0;
}
void tarjan(int u, int par, int id){
pt[id].push_back(u);
bel[u] = id;
dfn[u] = low[u] = ++idx;
mul[id] = mul[id] * w[u] % MOD;
int child = 0;
for(int v : G[u]){
if(v==par) continue;
if(!dfn[v]){
child++;
LL tmp = mul[ID];
tarjan(v,u,id);
low[u] = min(low[u],low[v]);
if(low[v]>=dfn[u]){
if(par) iscut[u] = true;
LL sub = mul[ID] * inv(tmp) % MOD;
// 由于不确定根节点是否是割点,所以先当作割点来处理
subsum[u] = (subsum[u] + sub) % MOD;
submul[u] = submul[u] * sub % MOD;
}
}
else low[u] = min(low[u],dfn[v]);
}
if(!par and child > 1) iscut[u] = true;
}
void solve(){
scanf("%d %d",&n,&m);
init();
for(int i = 1; i <= n; i++) scanf("%d",&w[i]);
for(int i = 1; i <= m; i++){
int u, v; scanf("%d %d",&u,&v);
G[u].push_back(v); G[v].push_back(u);
}
for(int i = 1; i <= n; i++) if(!dfn[i]){
pt[++ID].clear();
mul[ID] = 1;
tarjan(i,0,ID);
tot = (tot + mul[ID]) % MOD;
for(int x : pt[ID]){
if(x==i) continue;
subsum[x] = (subsum[x] + mul[ID] * inv(submul[x]*w[x]%MOD) % MOD) % MOD;
}
}
for(int i = 1; i <= n; i++){
LL res = 0;
if(iscut[i]) res = (tot - mul[bel[i]] + subsum[i] + MOD) % MOD;
else{
if(pt[bel[i]].size() == 1) res = (tot - w[i] + MOD) % MOD;
else res = (tot - mul[bel[i]] + mul[bel[i]] * inv(w[i]) % MOD + MOD) % MOD;
}
ans = (ans + i * res) % MOD;
}
printf("%I64d\n",ans);
}
int main(){
int tt;
for(scanf("%d",&tt); tt; tt--) solve();
return 0;
}

HDU5739 Fantasia【点双连通分量 割点】的更多相关文章

  1. poj 1523 SPF(双连通分量割点模板)

    题目链接:http://poj.org/problem?id=1523 题意:给出无向图的若干条边,求割点以及各个删掉其中一个割点后将图分为几块. 题目分析:割点用tarjan算法求出来,对于每个割点 ...

  2. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  3. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  4. (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)

    基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...

  5. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  6. Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板

    历时好几天,终于完工了! 支持无向图四种功能:1.割点的求解 2.割边的求解 3.点双连通分量的求解 4.边双连通分量的求解 全部支持重边!!!!全部支持重边!!!!全部支持重边!!!! 测试数据: ...

  7. CF487 E. Tourists [点双连通分量 树链剖分 割点]

    E. Tourists 题意: 无向连通图 C a w: 表示 a 城市的纪念品售价变成 w. A a b: 表示有一个游客要从 a 城市到 b 城市,你要回答在所有他的旅行路径中最低售价的最低可能值 ...

  8. 图论-桥/割点/双连通分量/缩点/LCA

    基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...

  9. Tarjan算法初探(3):求割点与桥以及双连通分量

    接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...

随机推荐

  1. Head First 设计模式 —— 11. 组合 (Composite) 模式

    思考题 我们不仅仅要支持多个菜单,升值还要支持菜单中的菜单.你如何处理这个新的设计需求? P355 [提示]在我们的新设计中,真正需要以下三点: P354 我们需要某种属性结构,可以容纳菜单.子菜单和 ...

  2. 【Docker】在Linux系统中安装Docker虚拟机、启动停止重启查看Docker命令

    安装Docker 文章目录 安装Docker Docker虚拟机架构 在Linux系统中安装Docker虚拟机 管理Docker虚拟机 参考资料 Docker虚拟机架构 Docker创建的所有虚拟实例 ...

  3. MySQL查询截取分析

    一.查询优化 1,mysql的调优大纲 慢查询的开启并捕获 explain+慢SQL分析 show profile查询SQL在Mysql服务器里面的执行细节和生命周期情况 SQL数据库服务器的参数调优 ...

  4. 使用call、apply、bind继承及三者区别

    js里的继承方法有很多,比如:使用原型链的组合继承.es6的Class.寄生继承以及使用call.apply.bind继承.再说继承之前,我们先简单了解下它们的区别. 一.区别: 同:三者都是改变函数 ...

  5. Java基础复习2

    三目运算符 语法:条件判断?表达式1:表达式2; 如果条件判断成立则获取值1否则获取值2 public class demo1{     public static void main(String[ ...

  6. 部署自动初始化Schema的数据库

    我们使用容器的方式部署数据库组件,特别是企业有大量的项目开发业务的,部署的开发.测试数据库组件较多时.经常会遇到以下问题: 业务需要使用数据库,但部署完数据库后,需要在数据库中执行创建schema的操 ...

  7. Jmeter接口自动化测试系列之函数使用及扩展

    介绍一下Jmeter自带函数的使用和 函数扩展,来满足测试工作中的各种需求! Jmeter自带函数 点击函数帮助助手图标,弹出函数助手框,可以选择各种各样的函数 举例: _Random 获取随机数,可 ...

  8. 计算机网络安全 —— C# 使用谷歌身份验证器(Google Authenticator)(五)

    一.Google Authenticator 基本概念  Google Authenticator是谷歌推出的一款动态口令工具,旨在解决大家Google账户遭到恶意攻击的问题,在手机端生成动态口令后, ...

  9. Canal介绍以及应用

    Canal介绍以及应用 应用场景: canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署, ...

  10. 类型检查 Type Checking 一些编程语言并不安全 类型化语言的优点 定型环境 (符号表) 断言的种类

    Compiler http://staff.ustc.edu.cn/~bjhua/courses/compiler/2014/ http://staff.ustc.edu.cn/~bjhua/cour ...