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 ...
随机推荐
- 安装Sublime Text 3插件的方法(转自Rising的博文)
安装Sublime Text 3插件的方法: 朋友们,小站活着不容易,全靠广告费养着了,如果本文对你有帮助.麻烦动下手点下页面的广告吧,谢谢! 直接安装 安装Sublime text 2插件很方便,可 ...
- 理解iOS Event Handling
写在前面 最近的一个iOS App项目中遇到了这么问题:通过App访问服务器的大多数资源不需要登录,但是访问某些资源是需要用户提供验证的,一般来说,通常App的做法(譬如美团App)将这些资源放在“我 ...
- BZOJ_1812_[Ioi2005]riv_树形DP
BZOJ_1812_[Ioi2005]riv_树形DP Description 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了 ...
- codeforces round 422 div2 补题 CF 822 A-F
A I'm bored with life 水题 #include<bits/stdc++.h> using namespace std; typedef long long int LL ...
- Hibernate中两种获取Session的方式
转自:https://www.jb51.net/article/130309.htm Session:是应用程序与数据库之间的一个会话,是hibernate运作的中心,持久层操作的基础.对象的生命周期 ...
- CClientDC类 CWindowDC类
CClientDC类 CClientDC类也是CDC类的派生类.它只能在窗口的客户区(即窗口中除了边框.标题栏.菜单栏以及状态栏外的中间部分)中进行绘图,坐标点(0,0)通常指的是客户区的左上角.它的 ...
- 【Codeforces Round #411 (Div. 1)】Codeforces 804C Ice cream coloring (DFS)
传送门 分析 这道题做了好长时间,题意就很难理解. 我们注意到这句话Vertices which have the i-th (1 ≤ i ≤ m) type of ice cream form a ...
- React的深入浅出
react组件重新渲染有两种途径:1.自身调用setState:2.父组件传入新的props.3.但这两种途径都不会必然调用render而引起重新渲染, 都会先经过shouldComponentUpd ...
- deque双向队列
对于双向队列,与队列queue以及vector容器的区别就在于,名字不同,也就是它是双向的,可以从头开始操作,也可以从末尾开始操作. 双向队列的常用方法跟队列queue差不多: 头文件: #inclu ...
- April Fools Contest 2017 F
Description You are developing a new feature for the website which sells airline tickets: being able ...