codeforces 949C - Data Center Maintenance【tarjan】
阿新 • • 發佈:2018-07-08
name 終端 () top add pac def oid sin
首先轉換圖論模型,把某個客戶一個終端的維修時間(+1)%h之後和另一個終端維修時間一樣,這樣的兩個終端連一條有向邊,表示推後一個終端就必須推後另一個
然後tarjan縮點,一個scc裏的終端是要一起推遲的,scc內點數為新圖點權
根據貪心的思想,在縮完點的DAG裏,一定是出度為0的點能獲得更小的值,因為出度不為零的點還要加上出邊所能到的點的點權
直接在出度為0的點裏取min,然後記一下更新答案的新點,最後把屬於這個新點的點的編號輸出即可
#include<iostream> #include<cstdio> using namespace std; const int N=1000005; int n,m,q,a[N],h[N],cnt,low[N],dfn[N],tot,bl[N],col,s[N],top,d[N],va[N],mn=1e9,w; bool v[N]; struct qwe { int ne,no,to; }e[N]; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v) { cnt++; e[cnt].ne=h[u]; e[cnt].no=u; e[cnt].to=v; h[u]=cnt; } void tarjan(int u) { dfn[u]=low[u]=++tot; v[s[++top]=u]=1; for(int i=h[u];i;i=e[i].ne) { if(!dfn[e[i].to]) { tarjan(e[i].to); low[u]=min(low[u],low[e[i].to]); } else if(v[e[i].to]) low[u]=min(low[u],dfn[e[i].to]); } if(low[u]==dfn[u]) { col++; while(s[top]!=u) { bl[s[top]]=col; va[col]++; v[s[top--]]=0; } bl[s[top]]=col; va[col]++; v[s[top--]]=0; } } int main() { n=read(),m=read(),q=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); if((a[x]+1)%q==a[y]) add(x,y); if((a[y]+1)%q==a[x]) add(y,x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=cnt;i++) if(bl[e[i].no]!=bl[e[i].to]) d[bl[e[i].no]]++; for(int i=1;i<=col;i++) if(!d[i]&&va[i]<mn) mn=va[i],w=i; printf("%d\n",mn); for(int i=1;i<=n;i++) if(bl[i]==w) printf("%d ",i); return 0; }
codeforces 949C - Data Center Maintenance【tarjan】