• 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;
    }
    
  • 相关阅读:
    Typora的使用
    selenium中webdriver提供的八大定位元素方法
    JAVA的Data和Timestamp的相互转换
    Jmeter设置参数作为断言依据
    Springboot +Poi 导入Excel表格
    window.location.reload();
    带参数的链接跳转
    Layui结束时间不能小于开始时间
    后台返回数据渲染Layui表格
    Layui中layedit模板的使用
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14273423.html
Copyright © 2020-2023  润新知