二分一下答案check即可。(拓扑排序)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define maxv 100500 #define maxe 200500 using namespace std; int n,m,nume=0,g[maxv],x[maxv],y[maxv],d[maxv],rank[maxv]; int cnt[maxv]; queue <int> q; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } bool check(int x) { int ret=0;while (!q.empty()) q.pop(); for (int i=1;i<=n;i++) {d[i]=0;rank[i]=-1;cnt[i]=0;} for (int i=1;i<=x;i++) d[y[i]]++; for (int i=1;i<=n;i++) { if (!d[i]) { if (ret) return false; q.push(i);ret++;rank[i]=1;cnt[1]++; } } while (!q.empty()) { int head=q.front();q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if (i>x) continue; if (!--d[v]) { rank[v]=rank[head]+1;cnt[rank[v]]++; q.push(v); } } } for (int i=1;i<=n;i++) { if (cnt[i]!=1) return false; } return true; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d",&x[i],&y[i]); addedge(x[i],y[i]); } int l=1,r=m,ans=-1; while (l<=r) { int mid=l+r>>1; if (check(mid)) {ans=mid;r=mid-1;} else l=mid+1; } printf("%d\n",ans); return 0; }
时间: 2024-10-26 16:58:36