HDU5739:Fantasia——题解

http://acm.hdu.edu.cn/showproblem.php?pid=5739

定义一个连通图的权值为所有顶点点权乘积,定义一个无向图的权值为这个无向图的所有极大连通子图权值和,现给出一张有$n$个点的无向图,每个点有点权$w_i$,设删去节点i后此图权值为$z_i$,求

圆方树处理一下可知删掉一个圆点后所形成的每个连通块里的圆点和你在原图删掉这个点后所形成的每个连通块里的点是一样的。

于是令$w[i]$为以$i$为根的子树的每个点的$w$的乘积,当然令方点的$w$为1,那么$z[u]=sigma(w[v])+sigma(w[rt])$,其中$v$是以$u$为根的树$u$的儿子,$rt$为其他的树的树根。

枚举每个圆点求解即可。

#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int p=1e9+7;
const int N=2e5+5;
const int M=4e5+5;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline ll qpow(ll k,int n){
    ll res=1;
    while(n){
        if(n&1)res=res*k%p;
        k=k*k%p;n>>=1;
    }
    return res;
}
struct node{
    int u[M],v[M],nxt[M];
    int cnt,head[N];
    void init(){
        cnt=0;
           memset(head,0,sizeof(head));
    }
    void add(int U,int V){
        u[++cnt]=U;v[cnt]=V;nxt[cnt]=head[U];head[U]=cnt;
    }
}e,g;
int n,m;
int dfn[N],low[N],to[N],t,l;
ll w[N];
stack<int>q;
void tarjan(int u,int f){
    dfn[u]=low[u]=++t;
    for(int i=g.head[u];i;i=g.nxt[i]){
        int v=g.v[i];
        if(!dfn[v]){
            q.push(i);
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                int num;l++;
                do{
                    num=q.top();q.pop();
                    int uu=g.u[num],vv=g.v[num];
                    if(to[uu]!=l){
                        to[uu]=l;
                        e.add(uu,l+n);e.add(l+n,uu);
                        w[l+n]=1;
                    }
                    if(to[vv]!=l){
                        to[vv]=l;
                        e.add(vv,l+n);e.add(l+n,vv);
                        w[l+n]=1;
                    }
                }while(num!=i);
            }
        }else if(low[u]>dfn[v]&&f!=v){
            q.push(i);
            low[u]=dfn[v];
        }
    }
}
ll ans,sum;
vector<int>root;
void dfs1(int u,int f){
    for(int i=e.head[u];i;i=e.nxt[i]){
        int v=e.v[i];
        if(f==v)continue;
        dfs1(v,u);w[u]=w[u]*w[v]%p;
    }
}
void dfs2(int u,int f,int rt){
    for(int i=e.head[u];i;i=e.nxt[i]){
        int v=e.v[i];
        if(f==v)continue;
        dfs2(v,u,rt);
        if(u<=n)ans=(ans+w[v]*u%p)%p;
    }
    if(u<=n){
        if(u!=rt)ans=(ans+w[rt]*qpow(w[u],p-2)%p*u%p)%p;
        ans=((ans+(sum-w[rt])*u%p)%p+p)%p;
    }
}
void init(){
    root.clear();
    for(int i=1;i<=n*2;i++){
        e.head[i]=g.head[i]=0;
        dfn[i]=low[i]=to[i]=0;
    }
    e.cnt=g.cnt=0;
    t=l=0;ans=sum=0;
}
int main(){
    int T=read();
    while(T--){
        n=read(),m=read();
        for(int i=1;i<=n;i++)w[i]=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            g.add(u,v);g.add(v,u);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                tarjan(i,0);dfs1(i,0);
                root.push_back(i);
                sum=(sum+w[i])%p;
            }
        }
        for(int i=0;i<root.size();i++){
            dfs2(root[i],0,root[i]);
        }
        printf("%lld
",ans);
        init();
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/12599343.html