zoukankan      html  css  js  c++  java
  • P4630-[APIO2018]Duathlon铁人两项【圆方树】

    正题

    题目链接:https://www.luogu.com.cn/problem/P4630


    题目大意

    (n)个点(m)条边的一张无向图,求有多少对三元组((s,c,f))满足(s eq f eq t)且存在一条从(s)(f)的简单路径经过(c)


    解题思路

    一个比较显然的结论是在一个点双中的三个点((a,b,c))那么必然存在一条(a)(b)的简单路径经过(c)。因为一定存在两条不交的(a->c)(c->b)的路径,那么如果一条(a->c)(c->b)的路径交了,那么另一条就一定不交。

    然后从一个点双出来后就不能再回到这个点双了,所以我们可以考虑在圆方树上做这个问题。

    设定义圆点的权值为(-1),方点的权值为连接的圆点数量,这样我们在圆方树上走的时候就可以固定经过进入和离开这个点双的点了。

    然后问题就变为了求每条圆点之间路径的点权和的和。

    用树形(dp)搞就好了,时间复杂度(O(n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<stack>
    using namespace std;
    const int N=2e5+10;
    int n,m,num,cnt,dfc,w[N];
    int low[N],dfn[N],siz[N];
    vector<int> G[N],T[N];
    stack<int> s;
    long long ans;
    void tarjan(int x){
        dfn[x]=low[x]=++dfc;
        w[x]=-1;s.push(x);num++;
        for(int y:T[x])
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
                if(dfn[x]==low[y]){
                    ++cnt;int k;
                    do{
                        k=s.top();
                        G[cnt].push_back(k);
                        G[k].push_back(cnt);
                        w[cnt]++;s.pop();
                    }while(k!=y);
                    G[cnt].push_back(x);
                    G[x].push_back(cnt);
                    w[cnt]++;
                }
            }
            else low[x]=min(low[x],dfn[y]);
        return;
    }
    void solve(int x,int fa){
        siz[x]=(x<=n);
        for(int y:G[x]){
            if(y==fa)continue;
            solve(y,x);
            ans+=2ll*siz[y]*siz[x]*w[x];
            siz[x]+=siz[y];
        }
        ans+=2ll*siz[x]*(num-siz[x])*w[x];
        return;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);
            T[x].push_back(y);
            T[y].push_back(x);
        }
        cnt=n;
        for(int i=1;i<=n;i++)
            if(!dfn[i]){
                num=0;
                tarjan(i);
                solve(i,0);
            }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    JQuery之在线引用
    SpringBoot之durid连接池配置
    VueJs之事件处理器
    VueJs之样式绑定
    VueJs之判断与循环监听
    PTA 7-8 暴力小学(二年级篇)-求出4个数字 (10分)
    PTA 7-7 交替字符倒三角形 (10分)
    PTA 7-5 阶乘和 (10分)
    PTA 7-4 哥德巴赫猜想 (10分)
    PTA 7-3 可逆素数 (15分)
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14273423.html
Copyright © 2011-2022 走看看