• 洛谷P3469 [POI2008]BLO-Blockade (Tarjan判割点+dfs树切割)


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

    题目解法:

    错解(50pts):我先用Tarjan跑了一把找到所有割点,因为非割点的话造成的影响肯定是2*(n-1),所以我们要特殊处理割点的情况。于是呢,我就把割点的相临点全部跑了一把bfs找该组有几个点,然后总点数带来的贡献-各个小组点数带来的贡献和就是最后答案。但是这个复杂度爆了TLE,所以只有50pts

    AC解法(100pts):利用tarjan的同时建立dfs树,因为low[v]>=dfn[x]就能判断x是不是割点。在dfs树上会有一些假子节点。而通过刚刚那个判断,我们可以把每一个真子结点进行处理,if(low[v]>=dfn[x]) siz[x]+=siz[v],这个情况就是真子节点因为low[v]和dfn[x]之间 >的情况是是一个单链,而=的情况是一个环。建成真的dfs树后,后面的处理就容易想了。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=5e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m;
    int id[maxn],dfn[maxn],low[maxn],tott,cnt;
    stack<int> s;int fa[maxn],cut[maxn];
    vector<int> bccs[maxn];int siz[maxn];ll ans[maxn];
    void tarjan(int x){
        low[x]=dfn[x]=++tott;
        s.push(x);int son=0;siz[x]=1;ll sum=0;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                ++son;fa[v]=x;
                tarjan(v);siz[x]+=siz[v];
                low[x]=min(low[x],low[v]);
                if(low[v]>=dfn[x]){
                    cut[x]=true;
                    ans[x]+=1LL*siz[v]*(n-1-siz[v]);        
                    sum+=siz[v];
                    ++cnt;
                    bccs[cnt].clear();
                    while(1){
                        int now=s.top();s.pop();
                        id[now]=cnt;
                        bccs[cnt].push_back(now);
                        if(now==v) break;
                    }
                    id[x]=cnt;
                    bccs[cnt].push_back(x);
                }
            }
            else if(v!=fa[x]) low[x]=min(low[x],dfn[v]);
        }
        if(fa[x]==-1&&son==1) cut[x]=false;
        if(!cut[x]) ans[x]=2*(n-1);
        else{
            ans[x]+=1LL*(n-sum-1)*(sum)+2*(n-1);
        }
    }
    int main(){
        cin>>n>>m;mem(head,-1);
        rep(i,1,m){
            int u,v;cin>>u>>v;
            add(u,v);add(v,u);
        }
        rep(i,1,n){
            if(!dfn[i]){fa[i]=-1;tarjan(i);}
        }
        rep(i,1,n){
            cout<<"TEST "<<dfn[i]<<" "<<low[i]<<endl;
        }
    }
    View Code
  • 相关阅读:
    记录下首次开通流量主,开心开心
    微信小程序之本地缓存
    在使用ef的情况下,有Migrations文件,想要直接生成数据库
    CSS 设置圆角div和阴影效果
    小程序UI库(UI组件)
    没有找到可以构建的 NPM 包---小程序开发
    php 接口参数对象转数组方法
    tp5框架获取随机n条
    php图片上传base64接口上传
    php如何实现定时任务,php定时任务方法,最佳解决方案,php自动任务处理
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13326253.html
Copyright © 2020-2023  润新知