CF915D Almost Acyclic Graph (思维+拓扑)

如果想要判定是否是DAG,用拓扑排序是一个好选择,但是本题可以删一条边

如果真的傻傻的去枚举删边就难顶了

我们要想到,对于删边,其实就是入度-1,而我们知道,删完能拓扑,说明成功了,因此只要枚举点,对入度操作再跑拓扑,就能AC

这个转化还是很有意思的,我们来思考正确性,首先对于一个环,肯定因为到了某个情况所有的入度都不为0,所以加不进队列。而对于环上一点,本来跑完拓扑之后就剩下环上的边,这次入度-1,相当于

忽略了环上的边,就成功了破解了,如果这个点上存在两个环,那还是没用,因为减完入度还有

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define ull unsigned long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e5+10;
int in[N],in1[N];
vector<int> g[N];
int n;
bool topo(){
    queue<int> q;
    int i;
    int sum=0;
    for(i=1;i<=n;i++){
        if(!in[i])
            q.push(i);
    }
    while(q.size()){
        int t=q.front();
        q.pop();
        sum++;
        for(i=0;i<g[t].size();i++){
            int j=g[t][i];
            in[j]--;
            if(!in[j])
                q.push(j);
        }
    }
    if(sum==n)
        return true;
    return false;
}
int main(){
    int i;
    int m;
    cin>>n>>m;
    for(i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        in[v]++;
        in1[v]++;
    }
    if(topo()){
        cout<<"YES"<<endl;
        return 0;
    }
    else{
        for(i=1;i<=n;i++){
            memcpy(in,in1,sizeof in);
            if(in[i]>=1){
                in[i]--;
                if(topo()){
                    cout<<"YES"<<endl;
                    return 0;
                }
            }
        }
    }
    cout<<"NO"<<endl;
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12633734.html