標籤:using string print for close turn data return ==
題意
有 n 個資訊中心,第 i 個資訊中心要在第 ti 個小時維護,維護期間資訊不能被獲得。
每個使用者的資料都有兩份備份,第 i 個使用者的資料放在資訊中心 c(i,1) 和 c(i,2)。
現在要挑選一個盡量小的資訊中心集合,使得將這個集合的維護時間延遲一個小時後,仍然能保證每個使用者的資料在任意時刻都能獲得。
n≤100000
題解對於每對 c(i,1),c(i,2),若調整 c(i,1) 後與 c(i,2) 的維護時間衝突,則連邊 (c(i,1), c(i,2) )對於 c(i,2),c(i,1) 亦然求出強連通分量,所求集合即為縮點後度數為 0 的最小的 SCC
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int N=500100; 8 int cnt,head[N]; 9 int dfn[N],low[N],stack[N],vis[N],w[N],c[N],num,tot,top;10 int n,m,h,t[N],ans,a[N],b[N],deg[N];11 struct edge{12 int to,nxt;13 }e[N];14 void add(int u,int v){15 cnt++;16 e[cnt].nxt=head[u];17 e[cnt].to=v;18 head[u]=cnt;19 }20 void Tarjan(int u){21 dfn[u]=low[u]=++tot;22 stack[++top]=u;23 vis[u]=1;24 for(int i=head[u];i;i=e[i].nxt){25 int v=e[i].to;26 if(dfn[v]==0){27 Tarjan(v);28 low[u]=min(low[u],low[v]);29 }30 else if(vis[v])low[u]=min(low[u],dfn[v]);31 }32 if(low[u]==dfn[u]){33 int x;34 num++;35 do{36 x=stack[top--];37 c[x]=num+n;38 w[num+n]++;39 add(num+n,x);40 vis[x]=0;41 }while(x!=u);42 }43 }44 int main(){45 scanf("%d%d%d",&n,&m,&h);46 for(int i=1;i<=n;i++){47 scanf("%d",&t[i]);48 }49 for(int i=1;i<=m;i++){50 scanf("%d%d",&a[i],&b[i]);51 if(t[a[i]]+1==t[b[i]]||(t[a[i]]==h-1&&t[b[i]]==0))add(a[i],b[i]);52 if(t[b[i]]+1==t[a[i]]||(t[b[i]]==h-1&&t[a[i]]==0))add(b[i],a[i]);53 }54 for(int i=1;i<=n;i++){55 if(dfn[i]==0)Tarjan(i);56 }57 for(int i=1;i<=m;i++){58 if(c[a[i]]==c[b[i]])continue;59 if(t[a[i]]+1==t[b[i]]||(t[a[i]]==h-1&&t[b[i]]==0))deg[c[a[i]]]++;60 if(t[b[i]]+1==t[a[i]]||(t[b[i]]==h-1&&t[a[i]]==0))deg[c[b[i]]]++;61 }62 int minn=9999999;63 for(int i=n+1;i<=n+num;i++){64 if(deg[i]==0&&minn>w[i]){65 minn=w[i];66 ans=i;67 }68 }69 printf("%d\n",w[ans]);70 for(int i=head[ans];i;i=e[i].nxt){71 int v=e[i].to;72 printf("%d ",v);73 } 74 return 0;75 } View Code
CF949C Data Center Maintenance(建圖+強聯通分量)