zoukankan      html  css  js  c++  java
  • CF1062F Upgrading Cities

    CF1062F Upgrading Cities 

    CF1062F]Upgrading Cities[拓扑排序]

     

    拓扑序好题

    直接处理到达集合,需要bitset

    其实不关心那么多。

    重要点:能到的和到它的sz=n-1

    次重要点:如果删除一个点之后重要,那么这个点一定只有一个不互相可达点。删除就删除它。

    我们只要考虑,多少点的互相可达集合sz>=n-2

    DAG考虑进行topo

    发现,任意时刻,队列中点两两不可达

    如果队列长度>2这些点都不用考虑了

    如果长度=1,后面的未进队点都可以到达

    =2,如果另一个点b后继有一个c当前入度是1,那么必然b,c都不可以由这个点到达。不用考虑了

    否则,未进队的点都可以到达。

    同时反向topo再来一边,就处理了能到x的点的个数。

    总个数>=n-2才可以。

    其实如果不用考虑,不做特殊处理,总个数就必然<n-2了

    简单证明正确性:

    1.重要点:一定会两次topo都在长度为1的时候出现,个数=n-1

    2.次重要点:唯一不互相可达的点,要么在之前出队,要么就是队列中的紧接着的一个。都考虑了。

    3.无贡献点:不互相可达的点很多,必然会存在一些点加不到集合里去。

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    namespace Modulo{
    const int mod=998244353;
    int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
    void inc(int &x,int y){x=ad(x,y);}
    int mul(int x,int y){return (ll)x*y%mod;}
    void inc2(int &x,int y){x=mul(x,y);}
    int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
    }
    //using namespace Modulo;
    namespace Miracle{
    const int N=300000+5;
    const int inf=0x3f3f3f3f;
    int n,m;
    int du[N];
    int b[N][2];
    vector<int>to[N];
    int go[N];
    int q[N],l,r,df;
    void topo(){
        l=1,r=0;df=0;
        for(reg i=1;i<=n;++i){
            if(du[i]==0) q[++r]=i;
        }
        while(l<=r){
            int x=q[l];++df;
            int sz=r-l+1;
            ++l;
            if(sz==1){
                go[x]+=n-df;
            }else if(sz==2){
                int b=q[l];
                int lp=0;
                for(solid y:to[b]){
                    if(du[y]==1) {lp=1;break;}
                }
                if(!lp){
                    go[x]+=n-df-1;
                }
            }
    
    
            for(solid y:to[x]){
                --du[y];
                if(du[y]==0){
                    q[++r]=y;
                }
            }
        }
    }
    int main(){
        rd(n);rd(m);
        for(reg i=1;i<=m;++i){
            rd(b[i][0]);rd(b[i][1]);
            to[b[i][0]].pb(b[i][1]);
            ++du[b[i][1]];
        }
        topo();
        for(reg i=1;i<=n;++i) to[i].clear(),du[i]=0;
        for(reg i=1;i<=m;++i){
            to[b[i][1]].pb(b[i][0]);  
            ++du[b[i][0]];
        }
        topo();
        int ans=0;
        for(reg i=1;i<=n;++i){
            if(go[i]>=n-2) ++ans;
        }
        ot(ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */  

    关键性质:topo序队列中点两两不可达。只在队列长度<=2时候才关心。

  • 相关阅读:
    URAL 1948 H
    int、long、long long取值范围
    Bonetrousle HackerRank 数学 + 思维题
    湖南省第十二届大学生计算机程序设计竞赛 problem A 2016
    Abbreviation ---- hackerrank
    POJ 3321 Apple Tree DFS序 + 树状数组
    HDU
    PICO CTF 2013 PHP 2: 85
    XSS进阶三
    XSS进阶二
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10937738.html
Copyright © 2011-2022 走看看