zoukankan      html  css  js  c++  java
  • [APIO2018] Duathlon 铁人两项

    题面在这里!

        填一下APIO时候的坑。。。

        其实就是圆方树的裸题。。。我们只要把圆方树建出来之后,分两种情况讨论一下就行了:不走回头路 和 只在某个方点(代表双联通分量的点)经过两次 的方案。。。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define pb push_back
    const int N=100005,M=400005;
     
    inline int read(){
        int x=0; char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x;
    }
     
    vector<int> g[N*2];
    int hd[N],to[M],ne[M],num,n,m,siz[N*2];
    int v[N],cnt,dc,dfn[N],low[N],nn;
    ll ans=0;
     
    struct lines{ int x,y;};
    stack<lines> S;
     
    inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;}
     
    void tarjan(int x,int fa){
        dfn[x]=low[x]=++dc,nn++;
        for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
            if(!dfn[to[i]]){
                S.push((lines){x,to[i]});
                tarjan(to[i],x),low[x]=min(low[x],low[to[i]]);
                 
                if(low[to[i]]>=dfn[x]){
                    cnt++; lines e;
                    for(e=S.top(),S.pop();;e=S.top(),S.pop()){
                        if(v[e.x]!=cnt) v[e.x]=cnt,g[cnt].pb(e.x),g[e.x].pb(cnt);
                        if(v[e.y]!=cnt) v[e.y]=cnt,g[cnt].pb(e.y),g[e.y].pb(cnt);
                         
                        if(e.x==x&&e.y==to[i]) break;
                    }
                }
            }
            else if(dfn[to[i]]<low[x]){
                S.push((lines){x,to[i]});
                low[x]=dfn[to[i]];
            }
    }
     
    void dfs(int x,int fa){
    	if(x<=n){
    		for(int i:g[x]) if(i!=fa)
    	        dfs(i,x),ans+=siz[x]*(ll)siz[i],siz[x]+=siz[i];
    		ans+=siz[x]*(ll)(nn-siz[x]-1);
    		siz[x]++;
    	}
    	else{
    		int sz=g[x].size()-2;
    		for(int i:g[x]) if(i!=fa)
    		    dfs(i,x),ans+=siz[x]*(ll)siz[i]*(ll)sz,siz[x]+=siz[i];
    		ans+=siz[x]*(ll)(nn-siz[x])*(ll)sz;
    	}
    }
     
    inline void solve(){
        for(int i=1;i<=n;i++) if(!dfn[i]){
            nn=0,tarjan(i,0);
            dfs(i,0);
        }
    }
     
    int main(){
        n=read(),m=read(),cnt=n;
        for(int i=1,uu,vv;i<=m;i++){
            uu=read(),vv=read();
            add(uu,vv),add(vv,uu);
        }
    	     
        solve();
         
        printf("%lld
    ",ans<<1);
        return 0;
    }
    
  • 相关阅读:
    ARM六种寻址方式的汇编实现
    生产者消费者
    哲学家问题
    linux进程的问题
    linux信号量使用
    linux进程创建
    Ubuntu下编写C语言程序
    Android使用图表库简单教程
    不需要SDK调用图灵机器人的方法
    robotframework接口测试实例
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9209616.html
Copyright © 2011-2022 走看看