Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <vector>
- #include <algorithm>
- #include <queue>
- #include <unordered_set>
- using namespace std;
- typedef vector<int> vi;
- typedef vector<vector<int> > vvi;
- void matar(int i, long long &ans, vi &dead, vi &lucro, vi &matador, vvi &mata){
- if(!dead[i]){
- queue<int> Q;
- Q.push(i);
- int cur;
- while(!Q.empty()){
- cur = Q.front();
- Q.pop();
- ans += lucro[matador[cur]];
- dead[cur] = 1;
- for(int m : mata[cur]) Q.push(m);
- }
- }
- }
- int main() {
- int n;
- scanf("%d", &n);
- vi f(n+1), p(n+1), m(n+1), lucro(n+1);
- vector<long long> s(n+1);
- vvi mata(n+1); // mata[i] = snacks que podem matar i
- vi matador(n+1); // matador de i mais lucrativo
- vi dead(n+1); // 1 = morreu
- p[0] = 1000001;
- for(int i = 1; i <= n; ++i) scanf("%d %d %d %I64d", &f[i], &p[i], &m[i], &s[i]);
- for(int i = 1; i <= n; ++i){
- lucro[i] = m[f[i]] - p[i];
- if(lucro[i] > 0){
- mata[f[i]].push_back(i);
- if(p[i] < p[matador[f[i]]]) matador[f[i]] = i;
- }
- }
- long long ans = 0;
- for(int i = 1; i <= n; ++i) if(!dead[i]) ans += (s[i] - 1)*(lucro[matador[i]]); // agora tudo 1
- for(int i = 1; i <= n; ++i) if(!dead[i] && lucro[i] <= 0) matar(i, ans, dead, lucro, matador, mata);
- for(int i = 1; i <= n; ++i){
- if(!dead[i]){
- // achar ciclo
- unordered_set<int> S;
- int a = i;
- while(S.count(a)==0){
- S.insert(a);
- a = f[a];
- }
- vi ciclo;
- ciclo.push_back(a);
- int next = f[a];
- while(next != a){
- ciclo.push_back(next);
- next = f[next];
- }
- int bad = 1;
- int c = ciclo.size();
- if(c==1) ans+= lucro[a];
- else{
- for(int j = 0; j < c && bad; ++j){
- if(matador[ciclo[j]]!=ciclo[(j-1+c)%c]){// pode matar geral..
- bad = 0;
- for(int v = (j-1+c)%c; v!=j; v = (v-1+c)%c) matar(ciclo[v], ans, dead, lucro, matador, mata);
- matar(ciclo[j], ans, dead, lucro, matador, mata);
- }
- }
- if(bad){// ciclo escroto..
- int otimo = 0;
- int curscore, curx;
- int second = 0;
- int minscore = p[0], minx = 0;
- for(int j = 0; j < c; ++j){
- second = 0;
- curscore = lucro[matador[ciclo[j]]];
- for(int x : mata[ciclo[j]]) if(x!=matador[ciclo[j]] && lucro[x] > second){
- second = lucro[x];
- curx = x;
- }
- curscore -= second;
- if(curscore < minscore){otimo = j; minscore = curscore; minx = curx;}
- }
- vi newmata; // tira o matador original..
- for(int x : mata[ciclo[otimo]]) if(x!=matador[ciclo[otimo]]) newmata.push_back(x);
- mata[ciclo[otimo]] = newmata; // muda o mata..
- matador[ciclo[otimo]] = minx; // agora pode matar tudo..
- for(int v = (otimo-1+c)%c; v!=otimo; v = (v-1+c)%c) matar(ciclo[v], ans, dead, lucro, matador, mata);
- matar(ciclo[otimo], ans, dead, lucro, matador, mata);
- }
- }
- }
- }
- printf("%I64d", ans);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement