Codeforces 950E Data Center Maintenance ( 思維 && 強連通分量縮點 )
阿新 • • 發佈:2018-04-28
strong namespace print 出入度 const 最優 span 圖片 max
題意 : 給出 n 個點,每個點有一個維護時間 a[i]。m 個條件,每個條件有2個點(x,y)且 a[x] != a[y]。選擇最少的 k (最少一個)個點,使其值加1後,m個條件仍成立。
分析 :
發現改變某些數加一後可能產生聯動效應
換句話說就是改變某些數則必須改變另一些數來維持 m 個條件的成立
這個可以用圖來表示,對於給出來的每一個 (x, y) 如果改變 x 後等於 y 則連 x => y 邊
表示要改變 x 則必須改變 y,然後對於 y 進行同樣的判斷是否連邊
最後建完圖後,若有成環的,則這個環上的點要加一改變,則環上所有點都必須進行改變
因此將整個圖進行強連通分量縮點,最後考察所有出度為 0 的的分量,哪個分量點最少
則這個點集就是答案,出度不為 0 的點肯定不是最優的,因為這些點定會回到出度為 0 的點
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; const int maxm = 2e5 + 10; struct EDGE{ int v, nxt; }Edge[maxm]; int Head[maxn], cnt; int DFN[maxn], LOW[maxn], color[maxn], INDEX, id; bool vis[maxn], out[maxn]; stack<int> stk; vectorView Code<int> num[maxn]; int N, M, H; inline void init() { while(!stk.empty()) stk.pop(); for(int i=0; i<=N; i++){ Head[i] = DFN[i] = LOW[i] = color[i] = -1; out[i] = false; num[i].clear(); }cnt = INDEX = id = 0; } inline void AddEdge(int from, int to) { Edge[cnt].v= to; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } inline void tarjan(int u) { DFN[u] = LOW[u] = INDEX++; stk.push(u); vis[u] = true; for(int i=Head[u]; i!=-1; i=Edge[i].nxt){ int Eiv = Edge[i].v; if(DFN[Eiv] == -1){ tarjan(Eiv); LOW[u] = min(LOW[u], LOW[Eiv]); }else{ if(vis[Eiv]) LOW[u] = min(LOW[u], LOW[Eiv]); } } if(DFN[u] == LOW[u]){ color[u] = ++id; num[id].push_back(u);; vis[u] = false; while(stk.top() != u){ vis[stk.top()] = false; color[stk.top()] = id; num[id].push_back(stk.top()); stk.pop(); } stk.pop(); } } int arr[maxn]; int main(void) { scanf("%d %d %d", &N, &M, &H); init(); for(int i=1; i<=N; i++) scanf("%d", &arr[i]); int u, v; while(M--){ scanf("%d %d", &u, &v); if((arr[u]+1)%H == arr[v]) AddEdge(u, v); if((arr[v]+1)%H == arr[u]) AddEdge(v, u); } for(int i=1; i<=N; i++) if(DFN[i] == -1) tarjan(i);///強連通分量縮點 for(int i=1; i<=id; i++){///統計縮點後每個點的出入度情況 for(int j=0; j<num[i].size(); j++){ u = num[i][j]; for(int k=Head[u]; k!=-1; k=Edge[k].nxt){ int Eiv = Edge[k].v; if(color[Eiv] != i){ out[i] = true; break; } } if(out[i]) break; } } int MM = 0x3f3f3f3f, which; for(int i=1; i<=id; i++){ if(!out[i] && num[i].size() < MM){ MM = num[i].size(); which = i; } } printf("%d\n", MM); for(int i=1; i<=N; i++) if(color[i] == which) printf("%d ", i); puts(""); return 0; }
Codeforces 950E Data Center Maintenance ( 思維 && 強連通分量縮點 )