1. 程式人生 > >題解 CF915D 【Almost Acyclic Graph】

題解 CF915D 【Almost Acyclic Graph】

mos 直接 eof name 想法 pos 把他 std sin

這道題我第一次的想法是直接判環的數量,然而事實證明實在是太naive了。

隨便畫個圖都可以卡掉我的解法。(不知道在想什麽)


這道題的正解是拓撲排序。

樸素的想法是對所有邊都跑一次拓撲,但這樣O(m(n+m))會炸,於是可以有下面的優化。

我們找到所有入度不為零的點,然後把他們每一個都刪掉一條邊跑一遍拓撲排序。

那麽這樣就可以優化到O(n(n+m))了,穩得一批。


AC代碼如下:

1935ms 1356kb

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 namespace
StandardIO { 6 7 template<typename T>inline void read (T &x) { 8 x=0;T f=1;char c=getchar(); 9 for (; c<0||c>9; c=getchar()) if (c==-) f=-1; 10 for (; c>=0&&c<=9; c=getchar()) x=x*10+c-0; 11 x*=f; 12 } 13 14 template<typename T>inline void
write (T x) { 15 if (x<0) putchar(-),x*=-1; 16 if (x>=10) write(x/10); 17 putchar(x%10+0); 18 } 19 20 } 21 22 using namespace StandardIO; 23 24 namespace Solve { 25 26 const int N=505; 27 28 int n,m; 29 vector<int>graph[N];
30 int indeg[N]; 31 queue<int>q; 32 33 inline bool toposort (int n) { 34 int temp[N],size=0; 35 memcpy(temp,indeg,sizeof(indeg)); 36 while (!q.empty()) q.pop(); 37 for (register int i=1; i<=n; ++i) { 38 if (temp[i]==0) q.push(i),size++; 39 } 40 while (!q.empty()) { 41 int v=q.front();q.pop(); 42 for (register int i=0; i<graph[v].size(); ++i) { 43 int to=graph[v][i]; 44 temp[to]--; 45 if (temp[to]==0) q.push(to),size++; 46 } 47 } 48 return size>=n; 49 } 50 51 inline void solve () { 52 read(n),read(m); 53 for (register int i=1; i<=m; ++i) { 54 int x,y; 55 read(x),read(y); 56 indeg[y]++; 57 graph[x].push_back(y); 58 } 59 for (register int i=1; i<=n; ++i) { 60 if (indeg[i]!=0) { 61 indeg[i]--; 62 if (toposort(n)) { 63 puts("YES"); 64 return; 65 } 66 indeg[i]++; 67 } 68 } 69 puts("NO"); 70 } 71 } 72 73 using namespace Solve; 74 75 int main () { 76 // freopen(".in","r",stdin); 77 // freopen(".out","w",stdout); 78 solve(); 79 }

題解 CF915D 【Almost Acyclic Graph】