zoukankan      html  css  js  c++  java
  • hdu5739

    以前从来没写过求点双连通分量,现在写一下……

    这题还用到了一个叫做block forest data structure,第一次见过……

    ——对于每一个点双联通分量S, 新建一个节点s, 向S中每个节点v连边. 这样一来, 新增的点和原来图中的点会构成一个森林

    主要是这个性质很厉害:

    【对于这个森林F, 删掉一个关键点或者一个叶子ii之后, 会得到一个新森林Fi, 这个Fi​​对应的连通块集合和Gi对应的连通块集合其实是一样的(不考虑那些新增的点)】

    更具体的题解见http://www.cnblogs.com/WABoss/p/5696926.html

    顺便学了一个扩大栈空间的方法:在编译器中加入命令--stack=16777216 (16777216相当于16MB空间)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<stack>
      7 typedef long long ll;
      8 using namespace std;
      9 const int mo=1000000007;
     10 struct edge{int x,y;};
     11 vector<int> g[300010];
     12 stack<edge> st;
     13 int dfn[300010],low[300010],f[100010],w[300010],s[300010],a[300010],root[300010],be[100010],fa[300010];
     14 bool cut[100010];
     15 int cas,n,m,t,h,x,y,sum;
     16 
     17 ll quick(ll x)
     18 {
     19   int y=mo-2; ll s=1;
     20   while (y)
     21   {
     22     if (y&1) s=s*x%mo;
     23     x=x*x%mo;
     24     y>>=1;
     25   }
     26   return s;
     27 }
     28 
     29 void dfs(int x)
     30 {
     31   dfn[x]=low[x]=++h;
     32   int chi=0;
     33   for (int i=0;i<g[x].size();i++)
     34   {
     35     int y=g[x][i];
     36     if (!dfn[y])
     37     {
     38       st.push((edge){x,i});
     39       fa[y]=x;dfs(y);
     40       chi++;
     41       low[x]=min(low[x],low[y]);
     42       if (low[y]>=dfn[x])
     43       {
     44         cut[x]=1;
     45         g[++t].clear();
     46         while (1)
     47         {
     48           int u=st.top().x,j=st.top().y;
     49           int v=g[u][j]; st.pop();
     50           if (be[u]!=t) {g[t].push_back(u); be[u]=t;}
     51           if (be[v]!=t) {g[t].push_back(v); be[v]=t;}
     52           if (u==x&&j==i) break;
     53         }
     54       }
     55     }
     56     else if (dfn[y]<dfn[x]&&fa[x]!=y)
     57     {
     58       st.push((edge){x,i});
     59       low[x]=min(low[x],dfn[y]);
     60     }
     61   }
     62   if (fa<0&&chi==1) cut[x]=0;
     63 }
     64 
     65 void dp(int x)
     66 {
     67   dfn[x]=root[h];
     68   if (x<=n) w[x]=a[x]; else w[x]=1;
     69   s[x]=0;
     70   for (int i=0; i<g[x].size(); i++)
     71   {
     72     int y=g[x][i];
     73     if (!dfn[y])
     74     {
     75       dp(y);
     76       w[x]=1ll*w[x]*w[y]%mo;
     77       s[x]=(s[x]+w[y])%mo;
     78     }
     79   }
     80 }
     81 
     82 int main()
     83 {
     84   freopen("1006.in","r",stdin);
     85   freopen("1006.ans","w",stdout);
     86   scanf("%d",&cas);
     87   while (cas--)
     88   {
     89     scanf("%d%d",&n,&m);
     90     for (int i=1; i<=n; i++)
     91     {
     92       dfn[i]=fa[i]=cut[i]=be[i]=0;
     93       scanf("%d",&a[i]);
     94     }
     95     for (int i=1; i<=m; i++)
     96     {
     97       scanf("%d%d",&x,&y);
     98       g[x].push_back(y);
     99       g[y].push_back(x);
    100     }
    101     t=n;
    102     for (int i=1; i<=n; i++)
    103       if (!dfn[i])
    104       {
    105         h=0;
    106         dfs(i);
    107       }
    108     for (int i=1; i<=n; i++) g[i].clear();
    109     for (int i=n+1; i<=t; i++)
    110       for (int j=0; j<g[i].size(); j++) {int x=g[i][j]; g[x].push_back(i);}
    111     for (int i=1; i<=t; i++) dfn[i]=f[i]=0;
    112     h=sum=0;
    113     for (int i=1; i<=t; i++)
    114       if (!dfn[i])
    115       {
    116         root[++h]=i;
    117         dp(i);
    118         sum=(sum+w[i])%mo;
    119       }
    120     for (int i=1; i<=n; i++)
    121     {
    122       if (dfn[i]==i) f[i]=0; else f[i]=1ll*w[dfn[i]]*quick(w[i])%mo;
    123       f[i]=((ll)f[i]+sum-w[dfn[i]]+s[i]+mo)%mo;
    124     }
    125     int ans=0;
    126     for (int i=1; i<=n; i++) ans=(ans+1ll*f[i]*i%mo)%mo;
    127     printf("%d
    ",ans);
    128     for (int i=1; i<=t; i++) g[i].clear();
    129   }
    130   return 0;
    131 }
    View Code
  • 相关阅读:
    MPI消息传递MPI_Sendrecv的用法
    外网SSH访问内网LINUX服务器
    LINUX下Doxygen的配置与使用
    C语言中关键字const一般的用途
    Ubuntu使用apt-get时提示>”E: You must put some ‘source’ URIs in your sources.list”
    C语言中复数运算及调用blas,lapack中复数函数进行科学计算
    linux系统下C语言调用lapack ,blas库
    一封家书,道尽顶尖人才的思维境界
    学会用麦肯锡的方式思考
    记得自己的大梦想
  • 原文地址:https://www.cnblogs.com/phile/p/5806682.html
Copyright © 2011-2022 走看看