HDU5739-Fantasia(tarjan求割点)
题意:给一个无向图n个点1~n,m条边,sigma(i*zi)%(1e9+7)。zi是这个图删掉i点之后的价值。一个图的价值是所有连通子图的价值之和,连通图的价值是每个点的乘积。
题解:讲道理这题不算难。注意一点就是一开始给的图不一定是连通的。然后就是割点会把一个连通图分成两个连通图,而其他点不影响图的连通性。至于割点直接tarjan就可以了。
而且dfs的过程中也可以处理出答案。这题只需要把每个连通子图求出而不需要处理出强连通分量,所以省去了tarjan算法中的stack数组。
变量比较多,写起来很烦。。
AC代码(1934MS):
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
typedef long long ll;
const int N = ;
const ll mod = 1e9+;
int n, m; // 同题目描述
int a[N]; // 记录每个点的权值 struct Edge // 前向星存边
{
int to, next;
} edge[N*];
int cnt_edge;
int head[N];
void add_edge(int u, int v)
{
edge[cnt_edge].to = v;
edge[cnt_edge].next = head[u];
head[u] = cnt_edge++;
} int dfn[N], low[N], idx; // tarjan中用到的变量 ll mul; // 临时变量,记录每个图的所有点乘积
ll ans[N]; // 对于每个割点 如果分割了这个点 这棵树的答案
ll smul[N]; // 对于每个割点 分割它后所有分出来的子树的乘积
bool cut[N]; // 割点
int graph_cnt; // 连通图数量
vector<int> G[N]; // 记录每个连通图
ll graph[N]; // 每个连通图所有点的乘积
int kind[N]; // 每个点属于哪个连通图 void init(int n)
{
for (int i = ; i <= n; ++i) {
head[i] = -;
dfn[i] = ;
ans[i] = ;
smul[i] = ;
cut[i] = false;
G[i].clear();
}
cnt_edge = ;
idx = ;
graph_cnt = ;
} ll pow_mod(ll x, ll n)
{
ll ans = ;
while (n) {
if (n & ) ans = ans * x % mod;
x = x * x % mod;
n >>= ;
}
return ans;
} void tarjan(int u, int fa)
{
dfn[u] = low[u] = ++idx;
int child = ;
G[graph_cnt].push_back(u);
kind[u] = graph_cnt;
mul = mul * a[u] % mod;
for (int i = head[u]; i != -; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
if (!dfn[v]) {
ll tmp = mul;
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) { // u是割点
++child;
ll inv = pow_mod(tmp, mod-);
tmp = mul * inv % mod; // mul/tmp 就是这个子图的乘积
ans[u] = (ans[u] + tmp) % mod;
smul[u] = smul[u] * tmp % mod;
}
} else {
low[u] = min(low[u], dfn[v]);
}
}
if ((fa == - && child > ) || (fa != - && child)) cut[u] = true; // u是割点
} int main(int argc, char const *argv[])
{
//freopen("in", "r", stdin);
int T;
cin >> T;
while (T--) {
scanf("%d%d", &n, &m);init(n);
for (int i = ; i <= n; ++i) scanf("%d", a+i);
int u, v;
while (m--) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
ll res = ;
for (int i = ; i <= n; ++i) {
if (!dfn[i]) {
mul = ;
tarjan(i, -);
graph[graph_cnt] = mul;
res = (res + mul) % mod;
for (unsigned j = ; j < G[graph_cnt].size(); ++j) {
u = G[graph_cnt][j];
if (u != i) {
ans[u] = (ans[u] + mul * pow_mod(smul[u]*a[u]%mod, mod - ) % mod) % mod; //mul/smul[j];
}
}
++graph_cnt;
}
}
ll rut = ;
for (int i = ; i <= n; ++i) {
ll tmp;
if (cut[i]) { // 如果是割点的话 就是这个点所在图分成多个子图
tmp = (res - graph[ kind[i] ] + ans[i] + mod) % mod;
} else {
if (G[kind[i]].size() == ) {
tmp = (res - a[i] + mod) % mod;
} else {
tmp = (res - graph[kind[i]] + graph[kind[i]] * pow_mod(a[i], mod-) % mod + mod) % mod;
}
}
rut = (rut + i * tmp % mod) % mod;
}
cout << rut << endl;
}
return ;
}
HDU5739-Fantasia(tarjan求割点)的更多相关文章
- UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数
Tarjan算法. 1.若u为根,且度大于1,则为割点 2.若u不为根,如果low[v]>=dfn[u],则u为割点(出现重边时可能导致等号,要判重边) 3.若low[v]>dfn[u], ...
- POJ 1144 Network(Tarjan求割点)
Network Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12707 Accepted: 5835 Descript ...
- poj 1523 SPF(tarjan求割点)
本文出自 http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...
- poj_1144Network(tarjan求割点)
poj_1144Network(tarjan求割点) 标签: tarjan 割点割边模板 题目链接 Network Time Limit: 1000MS Memory Limit: 10000K To ...
- 洛谷P3388 【模板】割点(割顶)(tarjan求割点)
题目背景 割点 题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入输出格式 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照 ...
- [POJ1144][BZOJ2730]tarjan求割点
求割点 一种显然的n^2做法: 枚举每个点,去掉该点连出的边,然后判断整个图是否联通 用tarjan求割点: 分情况讨论 如果是root的话,其为割点当且仅当下方有两棵及以上的子树 其他情况 设当前节 ...
- poj1144 tarjan求割点
poj1144 tarjan求割点 额,算法没什么好说的,只是这道题的读入非常恶心. 注意,当前点x是否是割点,与low[x]无关,只和low[son]和dfn[x]有关. 还有,默代码的时候记住分目 ...
- tarjan求割点割边的思考
这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...
- Tarjan求割点和桥
by szTom 前置知识 邻接表存储及遍历图 tarjan求强连通分量 割点 割点的定义 在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多, ...
- tarjan求割点与割边
tarjan求割点与割边 洛谷P3388 [模板]割点(割顶) 割点 解题思路: 求割点和割点数量模版,对于(u,v)如果low[v]>=dfn[u]那么u为割点,特判根结点,若根结点子树有超过 ...
随机推荐
- VC 最爱问的问题:你这个创业项目,如果腾讯跟进了,而且几乎是产品上完全复制,你会怎么办?
VC 最爱问的问题:你这个创业项目,如果腾讯跟进了,而且几乎是产品上完全复制,你会怎么办? http://www.zhihu.com/question/19607233 朱继玉,独立精神,自由思想. ...
- IDS 日志分析
[http://blog.csdn.net/cnbird2008/article/details/5792626] General Approach通用方法1. Identify which log ...
- Redis安装整理(window平台) +php扩展redis
window平台Redis安装 redis windows安装文件下载地址:http://code.google.com/p/servicestack/wiki/RedisWindowsDownloa ...
- linux ubuntu关于U盘的安装 开机启动u盘的时候出现/casper/vmlinuz.efi: file not found
将u盘下的/casper/vmlinuz文件添加一个后缀.efi即可. 重启再装.
- ASC #1
开始套题训练,第一套ASC题目,记住不放过每一题,多独立思考. Problem A ZOJ 2313 Chinese Girls' Amusement 循环节 题意:给定n,为圆环长度,求k < ...
- Vim插件列表
01.helm(Vim-Swoop) 02.ap/vim-buftabline 03.wesleyche/SrcExpl 04.vim proc 05.vim shell 06.dhruvasagar ...
- js标点符号全局匹配
var modelCode = node.modelCode.replace(/\./g, '\_'); 注意后面的 "\" <script language=" ...
- 【Pure】
PureA set of small, responsive CSS modules that you can use in every web project.http://purecss.io/
- JQuery: 微博演示
演示图: 完成图: 微博演示代码如下: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> ...
- android广告平台介绍
广告模式: 广告条:最普遍的广告模式,嵌入在应用界面内,用户点击行为会带来收入. 积分墙:应用通过限制功能.去广告等引导用户进入积分墙页面下载广告应用得到积分来换取使用的模式,用户安装完推荐广 ...