백준
백준 4013 ATM
콩순이냉장고
2025. 1. 15. 21:40
문제 URL : https://www.acmicpc.net/problem/4013
문제 접근법 :
scc + topology or bfs를 이용한문제입니다.
scc를 구성한후 새로운 그래프를 다시만들어준후
topology or bfs를 이용해서 최종답을 구해주면 됩니다.
자세한 건 소스코드 주석에 달았습니다.
소스코드:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
vector<vector<int>> v,scc_v;
vector<int> check,st,finished,atm,restaurant,scc_atm,dp;
vector<int> scc_restaurant,scc_indegree;
int n,m;
int s,p;
int cnt,scc;
void input(){
cin>>n>>m;
v= vector<vector<int>>(n+1);
scc_restaurant=scc_indegree=dp = scc_atm=restaurant=atm = check = finished = vector<int>(n+1);
int a,b;
for(int i=0;i<m;i++){
cin>>a>>b;
v[a].push_back(b);
}
for(int i =1;i<=n;i++){
cin>>a;
atm[i]=a;
}
cin>>s>>p;
for(int i=0;i<p;i++){
cin>>a;
restaurant[a]=1;
}
}
int dfs(int cur){
check[cur]=++cnt;
st.push_back(cur);
int result = check[cur];
for(int next:v[cur]){
if(!check[next])result = min(result,dfs(next));
else if(!finished[next])result = min(result,check[next]);
}
if(result==check[cur]){
scc++;
while(1){
int t = st.back();
st.pop_back();
finished[t]=scc;
if(t==cur)break;
}
}
return result;
}
int topology(){
int res = 0;
bool is_start=false;
queue<int> q;
//단순히 q.push(finished[s]) 이것만으로 불가능
for(int i=1;i<=scc;i++){
if(scc_indegree[i]==0){
q.push(i);
//dp[i]=scc_atm[i]; 이표현 불가능 거처가는 레스토랑이 아닐수도있기때문에
}
}
dp[finished[s]]=scc_atm[finished[s]];
while(!q.empty()){
int cur =q.front();
q.pop();
if(cur==finished[s])is_start=1;
for(int next:scc_v[cur]){
if(is_start)dp[next]=max(dp[next],dp[cur]+scc_atm[next]);
scc_indegree[next]--;
if(scc_indegree[next]==0)
q.push(next);
}
}
for(int i=1;i<=scc;i++){
if(scc_restaurant[i])
res =max(res,dp[i]);
}
return res;
}
int bfs(){
int res = 0;
queue<int> q;
q.push(finished[s]);
dp[finished[s]]=scc_atm[finished[s]];
while(!q.empty()){
int cur =q.front();
q.pop();
for(int next:scc_v[cur]){
if(dp[next]<dp[cur]+scc_atm[next]){
q.push(next);
dp[next]=dp[cur]+scc_atm[next];
}
}
}
for(int i=1;i<=scc;i++){
if(scc_restaurant[i]){
res = max(res,dp[i]);
}
}
return res;
}
void solve(){
//scc 구성
for(int i=1;i<=n;i++){
if(check[i]==0)
dfs(i);
}
scc_v = vector<vector<int>>(scc+1);
//scc의atm과 레스토랑 재구성
for(int i=1;i<=n;i++){
scc_atm[finished[i]]+=atm[i];
if(restaurant[i])scc_restaurant[finished[i]]=1;
}
//scc 의 그래프 재구성
for(int i=1;i<=n;i++){
for(int next:v[i]){
if(finished[i]==finished[next])continue;
scc_v[finished[i]].push_back(finished[next]);
scc_indegree[finished[next]]++;
}
}
//둘중 아무거나 사용가능
cout<<topology()<<"\n";
//cout<<bfs()<<"\n";
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
input();
solve();
}
위에 체점은 bfs를이용한것 아래는 topology를 이용한것
궁금한점 혹은 모르는점 혹은 논리적인 오류등 어떤 질문이라도 댓글은 언제나 환영입니다.