如果想要判定是否是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; }
原文地址:https://www.cnblogs.com/ctyakwf/p/12633734.html
时间: 2024-10-09 18:14:36