题意:给一个无向图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求割点)的更多相关文章

  1. UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数

    Tarjan算法. 1.若u为根,且度大于1,则为割点 2.若u不为根,如果low[v]>=dfn[u],则u为割点(出现重边时可能导致等号,要判重边) 3.若low[v]>dfn[u], ...

  2. POJ 1144 Network(Tarjan求割点)

    Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12707   Accepted: 5835 Descript ...

  3. poj 1523 SPF(tarjan求割点)

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  4. poj_1144Network(tarjan求割点)

    poj_1144Network(tarjan求割点) 标签: tarjan 割点割边模板 题目链接 Network Time Limit: 1000MS Memory Limit: 10000K To ...

  5. 洛谷P3388 【模板】割点(割顶)(tarjan求割点)

    题目背景 割点 题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入输出格式 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照 ...

  6. [POJ1144][BZOJ2730]tarjan求割点

    求割点 一种显然的n^2做法: 枚举每个点,去掉该点连出的边,然后判断整个图是否联通 用tarjan求割点: 分情况讨论 如果是root的话,其为割点当且仅当下方有两棵及以上的子树 其他情况 设当前节 ...

  7. poj1144 tarjan求割点

    poj1144 tarjan求割点 额,算法没什么好说的,只是这道题的读入非常恶心. 注意,当前点x是否是割点,与low[x]无关,只和low[son]和dfn[x]有关. 还有,默代码的时候记住分目 ...

  8. tarjan求割点割边的思考

    这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...

  9. Tarjan求割点和桥

    by szTom 前置知识 邻接表存储及遍历图 tarjan求强连通分量 割点 割点的定义 在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多, ...

  10. tarjan求割点与割边

    tarjan求割点与割边 洛谷P3388 [模板]割点(割顶) 割点 解题思路: 求割点和割点数量模版,对于(u,v)如果low[v]>=dfn[u]那么u为割点,特判根结点,若根结点子树有超过 ...

随机推荐

  1. What is the innovator’s solution——什么才是创新的解决方案1

    最近学习MOT(management of Technology),研读了Christensen的<创新者的窘境>和<创新者的解答>,以下简称创新者系列.总觉得需要写点儿什么. ...

  2. ASP.NET 访问 MySql

    1. 首先需要安装mysql, 脚本之家下载地址: http://www.jb51.net/softs/2193.html 或者去mysql.com官网都可以,一路next,安装好后,有个简单配置,提 ...

  3. C语言itoa()函数和atoi()函数详解(整数转字符)

    http://c.biancheng.net/cpp/html/792.html C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. 以下是用itoa()函数将整 ...

  4. 在Oracle 11g r2中,EXP无法导出个别空的表

    在Oracle 11g r2中,发现传统的exp无法不能导出空的表,上网搜索了一下找到了原因. 主要是Oracle 11g 新增了一个参数:deferred_segment_creation,含义是段 ...

  5. Javascript学习笔记(一)

    1.form表单中button按钮的事件会导致表单的提交,可以改成<input type='button'  /> 实现 2. 手动触发select的onchange事件 var sele ...

  6. jquery的smartWizard插件使用方法

    jquery 的smartWizard插件常用在一些向导式的,按步骤的功能中,是的用户按照我们设定的步骤进行操作,这样一方面有较好的用户体验,可以将庞大的表格 数据分解成多个步骤,是的每个步骤的数据量 ...

  7. HBase 的安装与配置

    实验简介 本次实验学习和了解 HBase 在不同模式下的配置和安装,以及 HBase 后续的启动和停止等. 一.实验环境说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shi ...

  8. P2P编程(十)

    此为网络编程的一个系列,后续会把内容补上....

  9. POJ 3207 Ikki's Story IV - Panda's Trick (2-SAT,基础)

    题意: 有一个环,环上n个点,现在在m个点对之间连一条线,线可以往圆外面绕,也可以往里面绕,问是否必定会相交? 思路: 根据所给的m条边可知,假设给的是a-b,那么a-b要么得绕环外,要么只能在环内, ...

  10. JDBC基础教程

    本文实例讲述了JDBC基础知识与技巧.分享给大家供大家参考.具体分析如下: 1.什么是JDBC? 通俗来讲JDBC技术就是通过java程序来发送SQL语句到数据库,数据库收到SQL语句后执行,把结果返 ...