zoukankan      html  css  js  c++  java
  • 洛谷P5058 [ZJOI2004]嗅探器(Tarjan找割点+思维处理dfn)

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

    思路:这个题其实想明白了就是一个很裸的找tarjan割点,但是这个割点的范围在(a,b)之间,即不包括a和b,所以我们可以考虑dfn,以a作为root点跑tarjan,然后判断是不是割点,再在割点的基础上判(dfn[v]是否小于等于dfn[b],因为是个回溯的过程嘛,如果b赋上了dfn的值,那么i肯定也有,如果b没附上,那i即使大于b且i是割点,那我们也不把他当成真割点)。最后rep(i,1,n)看一下最小的真割点是谁

     ps:这里我提一下为啥判的时候dfn[v]=dfn[b]的情况,emm这个情况其实就是这个割点x刚好在b前面那个点啦!注意对象是x!!

    #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 a,b;
    int id[maxn],dfn[maxn],low[maxn],tott,cnt;
    stack<int> s;int fa[maxn],cut[maxn];
    vector<int> bccs[maxn];
    void tarjan(int x){
        low[x]=dfn[x]=++tott;
        s.push(x);int son=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);
                low[x]=min(low[x],low[v]);
                if(low[v]>=dfn[x]){
                    if(dfn[v]<=dfn[b])cut[x]=true;
                    ++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;
    }
    int m,n;
    int main(){
        cin>>n;
        int u,v;mem(head,-1);
        while(cin>>u>>v&&u){
            add(u,v);add(v,u);
        }
        cin>>a>>b;
        tarjan(a);
        rep(i,1,n){
            if(i!=a&&cut[i]){
                cout<<i<<endl;return 0;
            }
        }
        puts("No solution");
    }
    View Code
  • 相关阅读:
    小总结:fibonacci数的产生
    pick the stone game
    温故知新的错题训练:Coin game
    《博弈论的诡计》
    思维+博弈论:字符串操作
    一下午的编程思索录
    2018中国大学生程序设计竞赛
    温故知新的经典贪心题目:今年暑假不AC?
    2019-2020新学的一些东西(持续更新)
    【半平面交】JZOJ3297. 【SDOI2013】逃考
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13332801.html
Copyright © 2011-2022 走看看