题意:给一个无向图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. 压缩/解压 zip 时遇到 java.lang.IllegalArgumentException: MALFORMED

    因为zip文件名为中文,或者压缩内容有中文 解决方法: 错误详情: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinde ...

  2. jmeter 响应结果分析二

    转自:http://www.cnblogs.com/Carrie_Liang/archive/2008/11/10/1330997.html 前文再续,续接上一回.上一篇讲了如何利用Assertion ...

  3. 深入剖析Classloader(一)--类的主动使用与被动使用

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220115573911607 我们知道java运行的是这样的,首先java编译器将我们 ...

  4. [模拟]ZOJ3485 Identification Number

    题意:给了一串15位或18位的身份证号码,求 在改变最少位数的情况下, 输出正确合法的身份证号 合法的身份证 是按照以下规则: 前6位以及“Order code”三位  一定合法 其中X是根据前17位 ...

  5. C++不同进制整数

    在C++的整数常量中,整数分为十进制整数.八进制整数和十六进制整数. 那给出一个整型常量怎样区分是何种进制呢?/给出一个整型常量,如100,默认是十进制数,如果在该数前加0,如0100,则此数表示为八 ...

  6. VPN+NAT实现代理服务器功能

    前话 用VPN+NAT再结合路由可以实现很方便的代理功能,适用于有一台能方便连接Internet的电脑,其他不在同一子网内的电脑能够连接到这台机器但不能完全访问Internet.比如好些学校的校园网, ...

  7. strlen的C/C+++实现

    2013-07-05 11:36:05 小结: 本函数给出了几种strlen的实现,有ugly implementation,也有good implementation.并参考标准库中的impleme ...

  8. C#创建XML文件并保存

    随着XML的普及以及在动态WEB应用程序中大量应用,如何通过.NET创建,删除,修改XML文件变的也来也重要了.一个简单的概念是,XML文件跟大的文本文件并没有什么区别,同时它是先于.NET出现,很多 ...

  9. Android开发之使用AlertDialog创建对话框,单选框和多选框

    对话框: 对话框的icon,title,message等都可以不设置. 单选框和多选框与对话框勾选步骤基本上一致. 对话框的构建步骤: 1.使用AlertDialog类的内部类Builder类new ...

  10. CSS那些事儿-阅读随笔1(CSS简介与选择符)

    最近开始详细钻研CSS有关的知识,参考资料是<CSS那些事儿>.将把在此过程中的收获进行记录,方便以后的学习. 一.CSS简介 1.什么是CSS CSS全称为Cascading Style ...