题意:给一个无向图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. HDU1796+容斥原理

    给定n和m个数,询问在小于n的数中 有多少个能整除m中的某个数.. 容斥原理. PS:注意64位整数! /* 容斥原理 */ #include<stdio.h> #include<s ...

  2. HDU1432+几何

    题意:给N个点,求最多有多少个点在同一直线上 方法一:求出所有能形成的直线,两两比较,统计最多有多少条重合. #include<stdio.h> #include<stdlib.h& ...

  3. Java 向Hbase表插入数据异常org.apache.hadoop.hbase.client.HTablePool$PooledHTable cannot be cast to org.apache.client.HTable

    出错代码如下: //1.create HTablePool HTablePool hp=new HTablePool(con, 1000); //2.get HTable from HTablepoo ...

  4. Android 通过http访问服务器

    目前Android 与服务器交互有两种方式:1.Socket 2. Http : 但由于Http的封装性以及性能比socket要好,所以推荐使用http方式和服务器交互: 通过http访问服务器有三种 ...

  5. C#连接SQLite的字符串

    一.C#在不同情况下连接SQLite字符串格式 1.Basic(基本的) Data Source=filename;Version=3; 2.Using UTF16(使用UTF16编码) Data S ...

  6. Consistent Hashing算法-搜索/负载均衡

    在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:  轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...

  7. C# CLR及程序集部署浅析

    摘 要 .NET Framework 到底是什么?公共语言运行时和 .NET Framework 类库分别指的是什么东西?CLR. CLS. CTS.FCL等这些又是什么?为什么出现程序集的概念?它与 ...

  8. bzoj1293

    简易贪心+heap 注意要用链表 type link=^node;      node=record        loc:longint;        next:link;      end;   ...

  9. 8款JS框架比较

    Dojo     Dojo 是目前最为强大的JS框架,它在自己的 Wiki 上给自己下了一个定义,Dojo 是一个用 JavaScript 编写的开源的DHTML工具箱.Dojo 很想做一个“大一统” ...

  10. I.MX6 Android Linux shell MMPF0100 i2c 获取数据

    #!/system/bin/busybox ash # # I.MX6 Android Linux shell MMPF0100 i2c 获取数据 # 说明: # 本文主要记录通过shell脚本来获取 ...