HDU5739 Fantasia【点双连通分量 割点】
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【点双连通分量 割点】的更多相关文章
- poj 1523 SPF(双连通分量割点模板)
题目链接:http://poj.org/problem?id=1523 题意:给出无向图的若干条边,求割点以及各个删掉其中一个割点后将图分为几块. 题目分析:割点用tarjan算法求出来,对于每个割点 ...
- 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 ...
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】
一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...
- (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板
历时好几天,终于完工了! 支持无向图四种功能:1.割点的求解 2.割边的求解 3.点双连通分量的求解 4.边双连通分量的求解 全部支持重边!!!!全部支持重边!!!!全部支持重边!!!! 测试数据: ...
- CF487 E. Tourists [点双连通分量 树链剖分 割点]
E. Tourists 题意: 无向连通图 C a w: 表示 a 城市的纪念品售价变成 w. A a b: 表示有一个游客要从 a 城市到 b 城市,你要回答在所有他的旅行路径中最低售价的最低可能值 ...
- 图论-桥/割点/双连通分量/缩点/LCA
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
- Tarjan算法初探(3):求割点与桥以及双连通分量
接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...
随机推荐
- ethernet
OSI参考模型 简化相关网络操作:提供不同厂商之间的互联 应用层 为应用程序提供服务 HTTP Telnet 表示层 数据格式化,加密.解密 ASCII EBCDIC JPEG 会话层 建立.维护.管 ...
- java对象
原文链接http://zhhll.icu/2020/04/26/java%E5%9F%BA%E7%A1%80/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/java%E5% ...
- go判断字符串是否是IP地址
前言 现在有这样的需求 正文 使用net包 net包的方法可以判断是否是 ip,需要注意的是 ip 分为 ipv4 和 ipv6 此方法将 v4 和 v6 一起判断出来 address := net. ...
- 设置.ignore后不生效解决方案
/logs/*.lock /logs/*.log/reports/API_TEST_V*/.idea/ 设置.ignore后不生效解决方案: 在terminal中输入已下几行代码: git rm -r ...
- kubernets之job资源
一 介绍job资源 1.1 前面介绍的RC,RS,DS等等,管控的pod都是需要长期持久的运行的应用,但是尝试考虑另外一种场景,在微服务的场景下,有些pod的作用就是需要 执行完一些命令之后正常 ...
- Hadoop 专栏 - MapReduce 入门
MapReduce的基本思想 先举一个简单的例子: 打个比方我们有三个人斗地主, 要数数牌够不够, 一种最简单的方法可以找一个人数数是不是有54张(传统单机计算); 还可以三个人各分一摞牌数各自的(M ...
- C# 中的动态类型
翻译自 Camilo Reyes 2018年10月15日的文章 <Working with the Dynamic Type in C#> [1] .NET 4 中引入了动态类型.动态对象 ...
- C++:I/O流的概念和流类库的结构
一.C++输入输出包含以下三个方面的内容: 对系统指定的标准设备的输入和输出.即从键盘输入数据,输出到显示器屏幕.这种输入输出称为标准的输入输出,简称标准I/O. 以外存磁盘文件为对象进行输入和输出, ...
- Caffeine 缓存库
介绍 Caffeine是一个基于Java8开发的提供了近乎最佳命中率的高性能的缓存库. 缓存和ConcurrentMap有点相似,但还是有所区别.最根本的区别是ConcurrentMap将会持有所有加 ...
- 对于Spring MVC 拦截器的一些了解
Spring MVC 拦截器的执行顺序 应用场景 假设请求 localhost:8080/ 则要求直接重定向到 localhost:8080/login ; 定义拦截器顺序 permission lo ...