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. ThreadX移植——STM32H7+MDK-AC6平台

    作者:zzssdd2 E-mail:zzssdd2@foxmail.com 一.前言 在uCOS全家桶宣布开源之后被微软收购的ThreadX也开源了,真是喜大普奔,对于我们这些嵌入式行业从业者来说,能 ...

  2. 【JavaWeb】i18n 国际化

    i18n 国际化 什么是 i18n 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问. 希望相同的一个网站,不同人访问的时候 ...

  3. 【栈和队列】2、栈的基本实现 - Java

    简单记录 - bobo老师的玩转算法系列–玩转数据结构 - 栈和队列 栈的实现 Stack<E> void push(E) E pop() E peek() int getSize() b ...

  4. 【Linux】iptables的内核模块问题大坑!

    系统环境 CentOS 6.5 今天本来可以平静的度过一天,正品味着下午茶的美好,突然接到防火墙iptables的报警. 进入到服务器中,执行下面的命令查看,结果报错 /etc/init.d/ipta ...

  5. 【Linux】用find删除大于30天的文件

    1.删除文件命令: find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \; 实例命令:find /opt/soft/log/ -mt ...

  6. Python3.9的http.client.py下的HTTPMessage类中的方法getallmatchingheaders的bug修复建议

    在官方网站已经提交相关issue,不过目前看好像还没有修复.具体的bug位置为: http文件夹下的client.py文件,代码位置为:类HTTPMessage下的方法getallmatchinghe ...

  7. 学习Java第三天

    方法重载:同一个类,方法名相同,参数不同(个数不同,类型不同,顺序不同),判断是否重载,只看方法名和参数,跟返回值无关. IDEA查看方法源代码:Crtl + 鼠标左键 进制表示 Java数值默认为十 ...

  8. java虚拟机入门(一)-jvm基础

    转行学java之前,总是听着大佬们说着java像个渣男一样可以跨平台,一次编译到处运行,瞬间,我就坚定了学java的信念,哎呀妈呀,得劲.真的学java之后,好像渣男也不是那么好学的,尤其这货的必杀技 ...

  9. (10)-Python3之--引入

    1.什么是模块 .py文件就是模块 模块名有命名要求: 1.不要以数字.下划线开头.特殊符号.也不要以中文开头. 2.通常来说,都是以字母开头. 3.不要以关键字来命名.内置函数.内置模块.不要以第三 ...

  10. git的使用学习笔记4--创建分支

    1.在git上新建分支 查看本地分支 git branch 查看远程分支 git branch -a 创建一个分支 git checkout -b branch1 再次查看远程分支可以看到该分支 2. ...