Fantasia

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description
Professor Zhang has an undirected graph G with n vertices and m edges. Each vertex is attached with a weight wi. Let Gi be the graph after deleting the i-th vertex from graph G. Professor Zhang wants to find the weight of G1,G2,...,Gn.

The weight of a graph G is defined as follows:

1. If G is connected, then the weight of G is the product of the weight of each vertex in G.
2. Otherwise, the weight of G is the sum of the weight of all the connected components of G.

A connected component of an undirected graph G is a subgraph in which any two vertices are connected to each other by paths, and which is connected to no additional vertices in G.

 
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers n and m (2≤n≤105,1≤m≤2×105) -- the number of vertices and the number of edges.

The second line contains n integers w1,w2,...,wn (1≤wi≤109), denoting the weight of each vertex.

In the next m lines, each contains two integers xi and yi (1≤xi,yi≤n,xi≠yi), denoting an undirected edge.

There are at most 1000 test cases and ∑n,∑m≤1.5×106.

 
Output
For each test case, output an integer S=(∑i=1ni⋅zi) mod (109+7), where zi is the weight of Gi.
 
Sample Input
1
3 2
1 2 3
1 2
2 3
 
Sample Output
20
 
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5739
 
题目描述:
  有n个节点,每个节点有个值,然后m条边构成可能不止一张张图,每张图的价值是每个节点的值的乘积,然后总的价值就是所有图的价值加起来。
现在要分别删除每个点,G1就是代表的删除编号为1的节点,所有图加起来的价值。 然后问你1*G[2] + 2*G[2] + ……+n*G[n]. 最后的值膜一个1e9+7。
 
题解:
  这个题很显然就是求割点,如果不是割点,就直接删除这个点就好了,如果是割点就复杂一点,就需要将该点的子树中最多能够访问到该点的子树的值给处理出来。然后把子树分开,另外处理就好了,还是看代码分析吧。道理是这么说,但是中途写错了好多东西TAT,对着数据改到现在...唉....
 
代码:  
 #include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#define inf 9223372036854775807
#define INF 9e7+5
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const db eps = 1e-9;
ll va[maxn], w[maxn], Sum, ans[maxn];
int pre[maxn], dfs_tim, tot, n, m, low[maxn], t, vep[maxn];
bool vis[maxn];
vector<int> G[maxn]; void init() {
memset(vis, false, sizeof(vis));
memset(pre, 0, sizeof(pre));
Sum = tot = dfs_tim = 0;
for (int i = 1; i <= n; i++) G[i].clear();
}
//快速幂,求逆元用
ll pow_mod(ll a, ll b, ll p) {
ll ret = 1;
while(b) {
if(b & 1) ret = (ret * a) % p;
a = (a * a) % p;
b >>= 1;
}
return ret;
}
//费马小定理求的逆元
ll inv(ll x) {
return pow_mod(x, mod-2, mod);
}
// 先写好,懒得每次模
void add(ll &x, ll y) {
x = x + y;
x = (x + mod) % mod;
}
// 主要是把每张图的价值处理出来
void Find(int x) {
va[x] = w[x];
for (int i = 0; i < G[x].size(); i++) {
int u = G[x][i];
if (vis[u]) continue;
vis[u] = true; Find(u);
va[x] = va[x] * va[u] % mod;
}
} ll dfs(int x, int fa, int root) { //当前节点,父节点和根节点
low[x] = pre[x] = ++dfs_tim; //pre数组记录访问的时间
ans[x] = inv(w[x]); //删除此时访问的节点
int cld = 0; ll sum = 0, res = w[x], pro = 1;
for (int i = 0; i < G[x].size(); i++) {
int u = G[x][i];
if (!pre[u]) {
cld++;
ll tmp = dfs(u, x, root); //tmp返回的是对于u这颗子树的价值
low[x] = min(low[x], low[u]); //更新x节点所能访问的最早的祖先
if (low[u] >= pre[x]) { //如果u这颗子树所能访问的是x,那么说明x节点被删除,u这颗子树会被分开
add(sum, tmp); //sum表示的是x节点被删除后,x会被分开的子树的价值之和
ans[x] = ans[x] * inv(tmp) % mod; //和上面删除节点一样,表示将这颗子树删除
}
res = res * tmp % mod; //求子树的价值
}
else if (u != fa) low[x] = min(low[x], pre[u]); //对于访问比当前节点早的节点,更新能访问的最早节点
} //tt表示的是除了这幅图,其它图的价值之和
ll tt = (Sum - va[root] + mod) % mod; //va[roor]*ans[x]中ans[x]已经是逆元了,所以这句话
ans[x] = va[root] * ans[x] % mod; //表示的是将x节点和会分开的子树 删除后该图的值
if (fa == -1 && ans[x] == 1) ans[x] = 0; //对于一张图,如果他的子节点全部被删除了,我们
    //求到的ans[x]是1,但事实上应 该是0,所以
//需要特判一下,比如这样一张图 1 - 2, 1 - 3.
add(ans[x], tt); add(ans[x], sum); //将其他图和删除的子树加起来
if (fa == -1) {
if (cld == 1) { //对于最开始的祖先,如果他只有一个儿
//子,那么他不是割点,学割点应该都学过QAQ
ans[x] = va[root] * inv(w[x]) % mod;
add(ans[x], tt);
}
else if (G[x].size() == 0) {
ans[x] = tt; //如果这是一个孤立点,删除后就直接是其他图的值
}
}
return res;
} void solve() {
cin >> n >> m;
init();
for (int i = 1; i <= n; i++) scanf("%I64d", &w[i]);
for (int i = 1; i <= m; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for (int i = 1; i <= n; i++) {
if (vis[i]) continue;
vis[i] = true;
vep[++tot] = i; Find(i); //vep数组用来存每次要访问的图的开始节点
add(Sum, va[i]); //所有图的总价值,va[i]就代表了这张图的总价值
}
for (int i = 1; i <= tot; i++) {
dfs(vep[i], -1, vep[i]); //-1位置代表的父节点,对于最开始的点的父亲设为-1
}
ll pri = 0;
for (ll i = 1; i <= n; i++) {
add(pri, i*ans[i]%mod); //求出最后的值
}
cout << pri << endl;
}
int main() {
//cin.sync_with_stdio(false);
// freopen("tt.txt", "r", stdin);
//freopen("hh.txt", "w", stdout);
cin >> t; while (t--)
solve();
return 0;
}

  

hdu5739Fantasia(多校第二场1006) 割点+逆元的更多相关文章

  1. hdu 6050: Funny Function (2017 多校第二场 1006) 【找规律】

    题目链接 暴力打个表找下规律就好了,比赛时看出规律来了倒是,然而看这道题看得太晚了,而且高中的那些数列相关的技巧生疏了好多,然后推公式就比较慢..其实还是自身菜啊.. 公式是 #include< ...

  2. 2019牛客多校第二场 A Eddy Walker(概率推公式)

    2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...

  3. 2015 多校赛 第二场 1006 (hdu 5305)

    Problem Description There are n people and m pairs of friends. For every pair of friends, they can c ...

  4. 2018 Multi-University Training Contest 2 杭电多校第二场

    开始逐渐习惯被多校虐orz  菜是原罪 1004  Game    (hdoj 6312) 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312 虽然披着 ...

  5. 2014多校第二场1011 || HDU 4882 ZCC Loves Codefires (贪心)

    题目链接 题意 : 给出n个问题,每个问题有两个参数,一个ei(所要耗费的时间),一个ki(能得到的score).每道问题需要耗费:(当前耗费的时间)*ki,问怎样组合问题的处理顺序可以使得耗费达到最 ...

  6. HDU 4612 (13年多校第二场1002)无向图缩点,有重边

    这道题是多校的题,比赛的时候是一道纷纷水过的板刷题. 题意:给你一些无向边,只加一条边,使该图的桥最少,然后输出最少的桥. 思路:当时大致想到思路了,就是缩点之后找出最长的链,然后用总的桥数减去链上的 ...

  7. 2019牛客多校第二场H-Second Large Rectangle

    Second Large Rectangle 题目传送门 解题思路 先求出每个点上的高,再利用单调栈分别求出每个点左右两边第一个高小于自己的位置,从而而得出最后一个大于等于自己的位置,进而求出自己的位 ...

  8. 2019年牛客多校第二场 H题Second Large Rectangle

    题目链接 传送门 题意 求在\(n\times m\)的\(01\)子矩阵中找出面积第二大的内部全是\(1\)的子矩阵的面积大小. 思路 处理出每个位置往左连续有多少个\(1\),然后对每一列跑单调栈 ...

  9. 第二大矩阵面积--(stack)牛客多校第二场-- Second Large Rectangle

    题意: 给你一幅图,问你第二大矩形面积是多少. 思路: 直接一行行跑stack求最大矩阵面积的经典算法,不断更新第二大矩形面积,注意第二大矩形可能在第一大矩形里面. #define IOS ios_b ...

随机推荐

  1. sscanf在字符串中的一些使用

    弟弟的作业 你的弟弟刚做完了"100以内数的加减法"这部分的作业,请你帮他检查一下.每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过 ...

  2. 区间DP 等腰三角形

    题目描述:给定一个正N边形,可以通过连线将这个多边形分割成N-2个三角形,问这N-2个三角形中恰有k个等腰三角形的分割方法有多少?这个值可能很大,输出对9397取模的结果.数据范围:n,k <= ...

  3. thinkpad开机引导方式变成PCI LAN选项解决

    问题:开机的引导方式变成[PCI LAN],并且前面有一个小箭头,无法正常启动加载.在BIOS中重置调整启动顺序也无法解决.无法进入U盘启动盘 1.首先开机按F12进入BIOS,选择 APP Menu ...

  4. POJ 3419 Difference Is Beautiful (DP + 二分 + rmq)

    题意:给n个数(n<=200000),每个数的绝对值不超过(10^6),有m个查询(m<=200000),每次查询区间[a,b]中连续的没有相同数的的最大长度. 析:由于n太大,无法暴力, ...

  5. CodeForces 719B Anatoly and Cockroaches (水题贪心)

    题意:给定一个序列,让你用最少的操作把它变成交替的,操作有两种,任意交换两种,再就是把一种变成另一种. 析:贪心,策略是分别从br开始和rb开始然后取最优,先交换,交换是最优的,不行再变色. 代码如下 ...

  6. hdoj5842【水题】

    比赛的时候还特别撒比地写了二分的那个写法,然后wa了一发,因为这个集合的翻译成自然数集.还是转换了一下,还是去写了一个二分. 后面就是出现几种就是多长... 比赛的真的非常非常挫的code-. #in ...

  7. bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ...

  8. P5024 保卫王国

    传送门 我现在还是不明白为什么NOIPd2t3会是一道动态dp-- 首先关于动态dp可以看这里 然后这里就是把把矩阵给改一改,改成这个形式\[\left[dp_{i-1,0},dp_{i-1,1}\r ...

  9. elasticsearch映射 mapping

    mapping的格式个应用,主要是创建索引(数据库)的时候指明type 的field类型,然后elasticsearch可以自动解析

  10. [BZOJ5120]无限之环

    Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...