1. 程式人生 > >cf950e Data Center Maintenance

cf950e Data Center Maintenance

true print cnblogs 答案 names -m gpo out div

若推遲 \(u\) 必推遲 \(v\),則連邊 <\(u,v\)>。
求強聯通分量後縮點,答案顯然是出度為 \(0\) 且 size 最小的 scc。

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, h, a[100005], dfn[100005], uu, vv, loo[100005], bel[100005], scc, hav[100005], sta[100005], din, tot;
int hea[100005], cnt, ru[100005], ans=0x3f3f3f3f, chu[100005], minn;
bool
ins[100005]; struct Edge{ int too, nxt; }edge[200005]; void add_edge(int fro, int too){ edge[++cnt].nxt = hea[fro]; edge[cnt].too = too; hea[fro] = cnt; } void tarjan(int x){ sta[++din] = x; ins[x] = true; dfn[x] = loo[x] = ++tot; for(int i=hea[x]; i; i=edge[i].nxt){ int
t=edge[i].too; if(!dfn[t]){ tarjan(t); loo[x] = min(loo[x], loo[t]); } else if(ins[t]) loo[x] = min(loo[x], dfn[t]); } if(dfn[x]==loo[x]){ int j; scc++; do{ j = sta[din--]; bel[j] = scc; hav[scc]++; ins[j] = false
; }while(dfn[j]!=loo[j]); } } int main(){ cin>>n>>m>>h; for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=m; i++){ scanf("%d %d", &uu, &vv); if((a[uu]+1)%h==a[vv]) add_edge(uu, vv); if((a[vv]+1)%h==a[uu]) add_edge(vv, uu); } for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); for(int i=1; i<=n; i++) for(int j=hea[i]; j; j=edge[j].nxt){ int t=edge[j].too; if(bel[i]!=bel[t]) chu[bel[i]]++; } for(int i=1; i<=scc; i++) if(!chu[i] && ans>hav[i]){ ans = hav[i]; minn = i; } cout<<ans<<endl; for(int i=1; i<=n; i++) if(bel[i]==minn) printf("%d ", i); printf("\n"); return 0; }

cf950e Data Center Maintenance