hdu 5739 割点

Fantasia

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1654    Accepted Submission(s): 429

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

/*
hdu 5739 割点

problem:
给你一个无向图,G[i]为删除i点时,无向图的价值.  求 sum(i*G[i])%mod
如果当前是连通的,那么连通分量的价值为所有点权值的积(任意两个节点连通)
否则为拆分后的各个连通分量的价值的和

solve:
所以需要判断当前点是否是割点.
如果不是割点,只需要减去这个点的权值即可. 如果是割点,要减去这个连通分量的价值再加上拆散后的各个连通分量的值

最开始题意理解错了- -,而且模板有点问题,一直wa.

hhh-2016-08-27 19:47:17
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfl(a) scanf("%I64d",&a)
#define key_val ch[ch[root][1]][0]
#define inf 1e9
using namespace std;
const ll mod = 1e9+7;
const int maxn = 100005;

struct Edge
{
    bool cut ;
    int v,next,w;
} edge[maxn*5];

int head[maxn],tot;
int low[maxn],dfn[maxn],Stack[maxn],index,top;
bool Instack[maxn],cut[maxn];
int bridge;
ll val[maxn],mul[maxn],ans[maxn],fans[maxn],tval[maxn];
void add_edge(int u,int v)
{
    edge[tot].v = v,edge[tot].next = head[u],head[u] = tot++;
}

ll tans  =1 ;

ll pow_mod(ll a,ll n)
{
    ll cnt =1 ;
    while(n)
    {
        if(n & 1) cnt = cnt*a%mod;
        a = a*a%mod;
        n >>= 1;
    }
    return cnt ;
}
int now;
vector<int> vec[maxn];
int from[maxn];
void Tarjan(int u,int ance,int pre)
{
    int v;
    vec[now].push_back(u);
    from[u] = now;
    low[u] = dfn[u] = ++index;
    Stack[top++] = u;
    Instack[u] = true;
    tans = tans*val[u] % mod;
    int son = 0;
    for(int i= head[u]; i!= -1; i = edge[i].next)
    {
        v = edge[i].v;
        if(v == pre){
            continue;
        }
        if(!dfn[v])
        {
            son ++ ;
            ll tp = tans;
            Tarjan(v,ance,u);
            low[u] = min(low[u],low[v]);

            if(u != pre && low[v] >= dfn[u])
            {
                cut[u] = true;
                ll ta = tans * pow_mod(tp,mod-2)%mod;
//                cout <<"node:" << u <<" ta:" <<ta <<endl;
                ans[u] = (ans[u] + ta)%mod;
                fans[u] = (fans[u] * ta) % mod;
            }
        }
        else if(low[u] > dfn[v])
            low[u] = dfn[v];
    }
    if(u == ance && son > 1)
        cut[u] = true;
    Instack[u] = false;
    top --;
}

void init(int n)
{
    for(int i = 0; i <= n+1; i++)
    {
        head[i] = -1;
        ans[i] = 0;
        fans[i] = 1;
        Instack[i]=cut[i]= 0;
        dfn[i] = 0;
        vec[i].clear();
    }
    tot=top=index=0;
}

int main()
{
//    freopen("in.txt","r",stdin);
    int T,n,m,u,v;

    scanfi(T);
    while(T--)
    {

        scanfi(n),scanfi(m);
        init(n);
        for(int i =1; i <= n; i++)
        {
            scanfl(val[i]);
            fans[i] = 1;
        }
        for(int i = 0; i < m; i++)
        {
            scanfi(u),scanfi(v);
            add_edge(u,v);
            add_edge(v,u);
        }
        now = 1;
        ll ob = 0;
        for(int i = 1; i <= n; i++)
        {
            if(!dfn[i])
            {
                tans= 1;
                Tarjan(i,i,-1);
                tval[now] = tans;
                ll amul = tans;
                ob = (ob+tans) %mod;
//                cout << "all:" <<tans<<endl;
                for(int j = 0 ; j < vec[now].size(); j ++)
                {
                    int to = vec[now][j];

//                    cout << to <<" " << fans[to] << endl;
                    if(to == i) continue;
                    ans[to] = (ans[to] + amul*pow_mod(fans[to]*val[to]%mod,mod-2)%mod);
                    if(ans[to] > mod) ans[to] -= mod;
                }
                now ++;
            }
        }
        ll out = 0;
        ll tm;
        for(int i = 1; i <= n; i++)
        {
//            cout << fans[i] <<" " << ans[i] <<" "  <<cut[i] << endl;
            int tf = from[i];
            if(cut[i])
            {
                tm = (ob - tval[tf] + ans[i] + mod)%mod;
            }
            else
            {
                if(vec[from[i]].size() > 1)
                    tm = (ob - tval[tf] + tval[tf]*pow_mod(val[i],mod-2)%mod + mod) % mod;
                else
                    tm = (ob - tval[tf] + mod) % mod;
            }
            out = (out + i * tm % mod) % mod;
        }
        printf("%I64d\n",out);
    }
    return 0;
}

/*
3
4 3
1 2 3 4
1 2
2 3
1 3

4 2
100000000 131231232 312354435 432134234
1 2
3 4

66
315142079

*/

  

时间: 2024-12-29 23:57:41

hdu 5739 割点的相关文章

HDU 5739 Fantasia

可以将这个图转换成森林来进行树形dp求解.看了这篇具体教学才会的:http://www.cnblogs.com/WABoss/p/5696926.html 大致思路:求解一下点双连通分量(Tarjan),新构造一个节点连向这个分量中每一个节点.每个点双连通分量都这样构造好之后,原本连通的一张图就形成了一棵树,并且这个树中拿掉一个节点之后的连通性和原图相同!因此,可以在树上求解答案(树dp即可). 注意:数据不一定保证原图是连通的,所以要特别注意原图中单个点的情况. #include<cstdio

HDU 4587 TWO NODES 枚举+割点

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4587 TWO NODES Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1448    Accepted Submission(s): 441 Problem Description Suppose that G is an undir

hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。

题意:求一个无向图的,去掉两个不同的点后最多有几个连通分量. 思路:枚举每个点,假设去掉该点,然后对图求割点后连通分量数,更新最大的即可.算法相对简单,但是注意几个细节: 1:原图可能不连通. 2:有的连通分量只有一个点,当舍去该点时候,连通分量-1: 复习求割点的好题! #include<iostream> #include<cstdio> #include<vector> using namespace std; int n,m; vector<vector&

HDU 4587 TWO NODES 割点

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4587 题意: 删除两个点,使连通块的数目最大化 题解: 枚举删除第一个点,然后对删除了第一个点的图跑割点更新答案. 代码: #include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> using namespace std; c

hdu 4587 判断孤立点+割点+ 删除点之后,剩下多少连通分量

做了很久...... 题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4587 先枚举删除的第一个点,第二个点就是找割点,没有割点当然也有答案 学到的: 1.图论硬套模板不太现实,比如这道题,我能想到孤立点是特殊情况,删除孤立点,连通分支个数会减少一,但是一直处理不好,最后按缩点的做法搞了, 判断是不是孤立点的方法: 就是先用一个数组scnt[i]=j,vv[j]++  表示点i在以j为祖先的联通分支里,而且每次都让vv[j]++,就使得vv[j

HDU 4587 无向图的割点

TWO NODES Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1137    Accepted Submission(s): 333 Problem Description Suppose that G is an undirected graph, and the value of stab is defined as fol

HDU 3749 Financial Crisis 经济危机(并查集,割点,双连通分量)

题意:给一个图n个点m条边(不一定连通),接下来又q个询问,询问两个点是为“不相连”,“仅有一条路径可达”,“有两条及以上的不同路径可达”三种情况中的哪一种.注:两条以上的路径指的是路径上的点连1个点也不重复. 思路:并查集+tarjan求割点. (1)情况一:先并查集处理,如果两个点从一开始就不连通,直接输出zero (2)情况二和情况三:两点既然连通,那么可能是只有1条路径,比如中间隔着一个割点:也可能有多条路径,比如在同一个双连通分量内.那么直接判断其是否在同一个双连通分量内即可,若在同一

HDU 3844 Mining Your Own Business(割点,变形,开栈,经典)

题意:给出一个连通图,要求将某些点涂黑,使得无论哪个点(包括相关的边)撤掉后能够成功使得剩下的所有点能够到达任意一个涂黑的点,颜料不多,涂黑的点越少越好,并输出要涂几个点和有多少种涂法. 思路: 要使得任意撤掉一个点都能使其他点能够到达黑点,那么点双连通分量能保证这点,那么就在同个点双连通分量内涂黑1个点.但是每个[点双连通分量]都涂吗?太浪费颜料了,那就缩点成树,只需要涂叶子即可,那就找度为1的缩点.但是种数呢?叶子内的点除了割点外都是可以涂黑的,因为如果黑色割点被撤掉,那么叶子中的其他点怎么

Key Vertex (hdu 3313 SPFA+DFS 求起点到终点路径上的割点)

Key Vertex Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1347    Accepted Submission(s): 305 Problem Description You need walking from vertex S to vertex T in a graph. If you remove one vert