1. 程式人生 > >CF949 C Data Center Maintenance——邊雙連通分量

CF949 C Data Center Maintenance——邊雙連通分量

font ORC 無語 ... max main tor back str

題目:http://codeforces.com/contest/949/problem/C

把一個點指向修改它會影響到的點就可以做了;

有取模,所以多出一些要註意的地方,首先是可能出現環,所以需要 tarjan 求邊雙;

其次,邊集數組的大小應該開成兩倍,因為取模可能導致一對 ci 互相連邊;

然後找出不影響別的點的、最小的邊雙,輸出即可;

而我竟然把 tarjan 都少寫了一個 top-- !真是對自己無語了...

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using
namespace std; int const maxn=1e5+5; int n,m,h,a[maxn],hd[maxn],cr,ct,col[maxn],sta[maxn],top,dfn[maxn],low[maxn],tim,deg[maxn]; bool vis[maxn]; vector<int>scc[maxn]; struct N{ int to,nxt; N(int t=0,int n=0):to(t),nxt(n) {} }ed[maxn<<1]; void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;}
void tarjan(int x) { dfn[x]=low[x]=++tim; sta[++top]=x; vis[x]=1; for(register int i=hd[x];i;i=ed[i].nxt) { int u=ed[i].to; if(!dfn[u]) { tarjan(u); low[x]=min(low[x],low[u]); } else if(vis[x])low[x]=min(low[x],dfn[u]); } if(low[x]==dfn[x]) { cr
++; while(sta[top]!=x) { int y=sta[top]; top--; vis[y]=0; col[y]=cr; scc[cr].push_back(y); } top--;//! vis[x]=0; col[x]=cr; scc[cr].push_back(x); } } int main() { scanf("%d%d%d",&n,&m,&h); for(register int i=1;i<=n;i++)scanf("%d",&a[i]); for(register int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); if((a[x]+1)%h==a[y])add(x,y); if((a[y]+1)%h==a[x])add(y,x); } for(register int i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(register int i=1;i<=n;i++) for(register int j=hd[i];j;j=ed[j].nxt) { int u=ed[j].to; if(col[i]!=col[u])deg[col[i]]++; } int mn=0x3f3f3f3f,tag; for(register int i=1;i<=cr;i++) if(!deg[i]&&scc[i].size()<mn)mn=scc[i].size(),tag=i; printf("%d\n",scc[tag].size()); for(register int j=0;j<scc[tag].size();j++) printf("%d ",scc[tag][j]); return 0; }

CF949 C Data Center Maintenance——邊雙連通分量