Fantasia (点强连通分量建图 + 树形DP)
简化一下题意,我们先看成一副强连通的图,这时候应该是最简单了,去点任意点都是其他的乘积。那再加强一点难度,改为两个强连通图连接的非强连通图呢?那应该就是找出关键的那个点,并求出两边的乘积。但是一个一个去找是不可能的。

假设如图中的非绿色线是题目给的图。然后我们根据强连通分量去新建一副如图中绿色线条的图,那么这时候我们就把原图转化为以可树了。。对于每一个点我们求的是该点以及以下的乘积。然后我们从A出发这时候我们发现A点的值刚好就是整幅图的乘积。这时候如果我们需要求删除3这个点的得到的结果应该就是整一副图去除以3点及一下的乘积得到1,2的乘积,再加上3点的子树的乘积和也就是4、5 和 6、7的乘积和。
这道题目的难点就是转化建图的那一个步骤,应该说是最核心的部分。
#include<bits/stdc++.h>
#define LL long long
using namespace std; const int maxn = 1e5 + ;
const LL mod = 1e9 + ; LL n, w[maxn], vis[maxn << 1], sum[maxn << 1], pro[maxn << 1]; struct oldEdge{
int v, next;
bool flag;
};
int oldHead[maxn], ocnt;
oldEdge oedge[maxn << ]; void addOldEdge(int u, int v){
oedge[ocnt].v = v;
oedge[ocnt].flag = false;
oedge[ocnt].next = oldHead[u];
oldHead[u] = ocnt ++;
} struct newEdge{
int v, next;
};
int newHead[maxn << ], ncnt;
newEdge nedge[maxn << ]; void addNewEdge(int u, int v){
nedge[ncnt].v = v;
nedge[ncnt].next = newHead[u];
newHead[u] = ncnt ++;
} int dfn[maxn], low[maxn], root[maxn], rn, cnt;
stack<int>sta; void tarjan(int u, int fa){
dfn[u] = low[u] = ++cnt;
for(int i = oldHead[u]; i != -; i = oedge[i].next){
if(oedge[i].flag) continue;
oedge[i].flag = oedge[i ^ ].flag = true;
sta.push(i);
int v = oedge[i].v; if(dfn[v]){
low[u] = min(low[u], dfn[v]);
continue;
}
tarjan(v, fa);
low[u] = min(low[u], low[v]); if(low[v] >= dfn[u]){
rn ++;
int ek;
do{
ek = sta.top();sta.pop();
root[oedge[ek].v] = root[oedge[ek ^ ].v] = fa;
addNewEdge(rn, oedge[ek].v); addNewEdge(oedge[ek].v, rn);
addNewEdge(rn, oedge[ek ^ ].v); addNewEdge(oedge[ek ^ ].v, rn);
}while(oedge[ek ^ ].v != u);
}
}
} void dfs(int u){
vis[u] = true;
sum[u] = ;
pro[u] = (u <= n) ? w[u] : ;
for(int i = newHead[u]; i != -; i = nedge[i].next){
int v = nedge[i].v;
if(vis[v]) continue;
dfs(v);
if(u <= n)
sum[u] = (sum[u] + pro[v]) % mod;
pro[u] = pro[u] * pro[v] % mod;
}
} LL inv(LL a){
int p = mod - ;
LL ret = ;
while(p){
if(p & )ret = ret * a % mod;
a = a * a % mod;
p >>= ;
}
return ret;
} void init(){
memset(root, , sizeof(root));
memset(newHead, -, sizeof(newHead));
memset(oldHead, -, sizeof(oldHead));
memset(dfn, , sizeof(dfn));
memset(vis, false, sizeof(vis));
ncnt = ocnt = cnt = ;
} int main(){
int T, m, a, b;scanf("%d",&T);
while(T --){
scanf("%lld%d",&n,&m);
init();rn = n;
for(int i = ; i <= n; i ++)scanf("%lld",&w[i]);
for(int i = ; i < m; i ++){
scanf("%d%d",&a,&b);
addOldEdge(a,b);
addOldEdge(b,a);
}
for(int i = ; i <= n; i ++)
if(!dfn[i])tarjan(i, rn + ); LL tot = ;
for(int i = ; i <= n; i ++){
if(vis[i]) continue;
if(root[i]){
dfs(root[i]);
tot = (tot + pro[root[i]]) %mod;
}else
tot = (tot + w[i]) % mod;
}
LL ans = ;
for(int i = ; i <= n; i ++){
if(root[i]){
LL temp = ((tot - pro[root[i]] + pro[root[i]] * inv(pro[i]) + sum[i]) % mod + mod) * i % mod;
ans = (ans + temp) % mod;
}
else
ans = ((ans + (tot - w[i]) * i) % mod + mod) % mod;
}
printf("%lld\n",ans);
}
return ;
}
Fantasia (点强连通分量建图 + 树形DP)的更多相关文章
- bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]
4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...
- 【HDU5934】Bomb——有向图强连通分量+重建图
题目大意 二维平面上有 n 个爆炸桶,i−thi-thi−th爆炸桶位置为 (xi,yi)(x_i, y_i)(xi,yi) 爆炸范围为 rir_iri ,且需要 cic_ici 的价格引爆, ...
- 强连通 反向建图 hdu3639
Hawk-and-Chicken Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- poj1949Chores(建图或者dp)
/* 题意:n个任务,有某些任务要在一些任务之前完成才能开始做! 第k个任务的约束只能是1...k-1个任务!问最终需要最少的时间完成全部的 任务! 思路:第i个任务要在第j个任务之前做,就在i,j之 ...
- 深探树形dp
看到同学在写一道树形dp,好奇直接拿来写,发现很不简单. 如图,看上去是不是很像选课,没错这不是选课,升级版吧,多加了点东西罢了.简单却调了一晚上和一上午. 思路:很简单强联通分量+缩点+树形dp.直 ...
- Tarjan算法 求 有向图的强连通分量
百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...
- poj 2186 tarjan求强连通分量
蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了! 顺便借这个题记录一下求强连通分量的算法 1 只需要一次dfs 依靠stack来实现的tarjan算 ...
- POJ 3107.Godfather 树形dp
Godfather Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7536 Accepted: 2659 Descrip ...
- Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量
在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...
随机推荐
- Java之旅_面向对象_多态
参考并摘自:http://www.runoob.com/java/java-polymorphism.html 多态 多态是一个行为具有多个不同表现形式的能力. 多态就是同一个接口,使用不同的实例而执 ...
- activeMQ配置文件
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agree ...
- .net core开发工具与SDK
一.开发工具 开发工具使用Visual Studio 2017 下载官网:https://visualstudio.microsoft.com/zh-hans/vs/ 相关的安装已经有很多文章介绍过, ...
- 关于安装SVN Service 出错 Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details
关于安装SVN Service 出错 Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in ...
- Spring事务管理详解_基本原理_事务管理方式
1. 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交,那在没有Spring帮我们管理事 ...
- 关于ios下字体描边的一个细节
转载请注明,来自:http://blog.csdn.net/skyman_2001 CGContextSetTextDrawingMode(context, kCGTextStroke); ...
- 并发编程---IO模型
IO模型 任务的提交方式有两种: 同步:应用程序提交完任务,等待结果结果,之后在执行下一个任务 异步:应用程序提交完任务,继续执行不等待结果,任务执行完,会自动出发异步中的会带哦函数 同步不等于阻塞: ...
- PHP注册器模式
[Register.class.php] <?php /** * 注册器模式 * 全局共享和交换对象 */ class Register { protected static $objects; ...
- MySQL 基础 备份和恢复
数据库备份 mysqldump [args] > file_name 例如:备份所有数据库 shell> mysqldump --all-databases > dump.sql # ...
- JS快速入门
字符串 模板字符串 需要特别注意的是,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果: var s = 'Test'; s[0] = 'X'; alert(s); ...