CF1062F Upgrading Cities

http://codeforces.com/problemset/problem/1062/F

题解

有意思的题。

首先考虑在\(DAG\)上拓扑的过程,设当前队列中的点集为\(S\),那么有结论是这些点之间都不能互相到达,这个比较好理解。

那么我们考虑在弹出一个点的时候计算它能够到达多少点,如果当前队列里有超过一个点,那它肯定就不行了。

如果一个点都没有,那么剩下的点他都可以访问。

如果只有一个点,那么看一下那个点的所有出点,如果有一个点的入度为1,说明当前这个点一定不能到达,否则一定全都能到达,这个可以手画理解一下。

但是还要计算它被多少点到达,这个反着拓扑一下就好了。

代码

#include<bits/stdc++.h>
#define N 300009
using namespace std;
typedef long long ll;
queue<int>q;
int n,m,du1[N],du2[N],ans,f[N];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
std::vector<int>vec1[N],vec2[N];
std::vector<int>::iterator it;
inline void add(int u,int v){
    vec1[u].push_back(v);du1[v]++;
    vec2[v].push_back(u);du2[u]++;
}
int main(){
    n=rd();m=rd();
    for(int i=1;i<=n;++i)f[i]=1;
    int u,v;
    for(int i=1;i<=m;++i){
        u=rd();v=rd();
        add(u,v);
    }
    int now=n;
    for(int i=1;i<=n;++i)if(!du1[i])q.push(i),now--;
    while(!q.empty()){
        int u=q.front();q.pop();
        if(!q.size())f[u]+=now;
        else if(q.size()==1){
            int v=q.front(),o=0;
            for(it=vec1[v].begin();it!=vec1[v].end();++it){
                int w=*it;
                if(du1[w]==1){o=1;break;}
            }
            if(!o)f[u]+=now;
        }
        for(it=vec1[u].begin();it!=vec1[u].end();++it){
            int v=*it;
            if(!--du1[v])q.push(v),now--;
        }
    }
    now=n;
    for(int i=1;i<=n;++i)if(!du2[i])q.push(i),now--;
    while(!q.empty()){
        int u=q.front();q.pop();
        if(!q.size())f[u]+=now;
        else if(q.size()==1){
            int v=q.front(),o=0;
            for(it=vec2[v].begin();it!=vec2[v].end();++it){
                int w=*it;
                if(du2[w]==1){o=1;break;}
            }
            if(!o)f[u]+=now;
        }
        for(it=vec2[u].begin();it!=vec2[u].end();++it){
            int v=*it;
            if(!--du2[v])q.push(v),now--;
        }
    }
    for(int i=1;i<=n;++i){
      if(f[i]>=n-1)ans++;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ZH-comld/p/11032046.html
今日推荐