hdu5739Fantasia(多校第二场1006) 割点+逆元
Fantasia
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
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.
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.
3 2
1 2 3
1 2
2 3
#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) 割点+逆元的更多相关文章
- hdu 6050: Funny Function (2017 多校第二场 1006) 【找规律】
题目链接 暴力打个表找下规律就好了,比赛时看出规律来了倒是,然而看这道题看得太晚了,而且高中的那些数列相关的技巧生疏了好多,然后推公式就比较慢..其实还是自身菜啊.. 公式是 #include< ...
- 2019牛客多校第二场 A Eddy Walker(概率推公式)
2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...
- 2015 多校赛 第二场 1006 (hdu 5305)
Problem Description There are n people and m pairs of friends. For every pair of friends, they can c ...
- 2018 Multi-University Training Contest 2 杭电多校第二场
开始逐渐习惯被多校虐orz 菜是原罪 1004 Game (hdoj 6312) 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312 虽然披着 ...
- 2014多校第二场1011 || HDU 4882 ZCC Loves Codefires (贪心)
题目链接 题意 : 给出n个问题,每个问题有两个参数,一个ei(所要耗费的时间),一个ki(能得到的score).每道问题需要耗费:(当前耗费的时间)*ki,问怎样组合问题的处理顺序可以使得耗费达到最 ...
- HDU 4612 (13年多校第二场1002)无向图缩点,有重边
这道题是多校的题,比赛的时候是一道纷纷水过的板刷题. 题意:给你一些无向边,只加一条边,使该图的桥最少,然后输出最少的桥. 思路:当时大致想到思路了,就是缩点之后找出最长的链,然后用总的桥数减去链上的 ...
- 2019牛客多校第二场H-Second Large Rectangle
Second Large Rectangle 题目传送门 解题思路 先求出每个点上的高,再利用单调栈分别求出每个点左右两边第一个高小于自己的位置,从而而得出最后一个大于等于自己的位置,进而求出自己的位 ...
- 2019年牛客多校第二场 H题Second Large Rectangle
题目链接 传送门 题意 求在\(n\times m\)的\(01\)子矩阵中找出面积第二大的内部全是\(1\)的子矩阵的面积大小. 思路 处理出每个位置往左连续有多少个\(1\),然后对每一列跑单调栈 ...
- 第二大矩阵面积--(stack)牛客多校第二场-- Second Large Rectangle
题意: 给你一幅图,问你第二大矩形面积是多少. 思路: 直接一行行跑stack求最大矩阵面积的经典算法,不断更新第二大矩形面积,注意第二大矩形可能在第一大矩形里面. #define IOS ios_b ...
随机推荐
- 「网络流24题」「LuoguP4015」 运输问题
Description W 公司有 m 个仓库和 n 个零售商店.第 i 个仓库有 ai 个单位的货物:第 j 个零售商店需要 bj 个单位的货物. 货物供需平衡,即 ∑ai=∑bj . 从第 i ...
- nodejs QueryString模块 详解
QueryString模块 "QueryString" 模块用于实现URL参数字符串与参数对象的互相转换 此类一共包括4个方法: querystring.stringify(obj ...
- Spring MVC访问页面直接显示源码
转自:https://blog.csdn.net/u011781521/article/details/78751253
- CodeForces 719A Vitya in the Countryside (水题)
题意:根据题目,给定一些数字,让你判断是上升还是下降. 析:注意只有0,15时特别注意一下,然后就是14 15 1 0注意一下就可以了. 代码如下: #pragma comment(linker, & ...
- E20170505-ms
respectively adv. 分别,各自,顺序 为,依次为 encryption n.加密 corresponding adj. 符合的,相应的,相关的 correspond v. 通信,符合, ...
- 51nod 1138 【数学-等差数列】
思路: 很显然每个连续的序列都是等差数列, 那么我们利用等差数列求和公式. S=(a1+a1+k-1)k/2=(2·a1+k-1)*k/2;a1是首项,k是个数. 枚举k,首项最小为1,k最大,具体不 ...
- hdoj3790 【最短路】
这一题啊,其实还是很简单的~(A掉了就很简单啊~) 思路: 松弛,然后在里面维护一个小最短路~: A掉这一题,感觉松弛的理解又上了一个台阶,以及spfa的原理,最短路用到的原理就是松弛,先把图构造到最 ...
- bzoj 5499: [2019省队联测]春节十二响【堆】
首先看两条链怎么合并,贪心可得是从大到小取max,多条链同理 所以dfs合并子树的大根堆即可,注意为了保证复杂度,合并的时候要合并到最长链上,证明见长链剖分 #include<iostream& ...
- Java反编译工具-JD-GUI
Java是跨平台的,JD-GUI提供了多个系统的支持,但是不建议直接安装,最快的方式推荐直接下载JAR包,然后用java -jar进行运行. 就现在的版本是1.4.0,停留在2015年,估计近期会更新 ...
- 跟我一起玩Win32开发(10):绘图(C)
今天我们来欣赏一下用于填充图形的函数,当然我不会逐个去介绍,因为我们参考MSDN直接套参数就可以了. SetDCBrushColor函数有必要扯一下,它的声明如下: COLORREF SetDCBru ...