WA35pts求调!qwq
查看原帖
WA35pts求调!qwq
1415116
Index2010楼主2024/12/13 22:39

没有用大家用的单调队列,但大体思路一样,代码应该很好懂了

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
// typedef __int128 int128;
typedef pair<int , int > pii;
typedef unsigned long long ull;

namespace FastIO 
{
    // char buf[1 << 20], *p1, *p2;
    // #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
    template<typename T> inline T read(T& x) {
        x = 0;
        int f = 1;
        char ch;
        while (!isdigit(ch = getchar())) if (ch == '-') f = -1;
        while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
        x *= f;
        return x;
    }
    template<typename T, typename... Args> inline void read(T& x, Args &...x_) {
        read(x);
        read(x_...);
        return;
    }
    inline ll read() {
        ll x;
        read(x);
        return x;
    }
};
using namespace FastIO;

template<int N, int M>
class Graph {
    private :
        struct Edge {
            int to, nt, wt;
            Edge() {}
            Edge(int to, int nt, int wt) : to(to), nt(nt), wt(wt) {}
        }e[M];
        int hd[N], cnte;
    public :
        inline void clear() { memset(hd, 0, sizeof(hd)), cnte = 0; }
        inline void AddEdge(int u, int v, int w = 0) {
            e[++cnte] = Edge(v, hd[u], w);
            hd[u] = cnte;
        }
        inline int head(int u) { return hd[u]; }
        inline int nt(int u) { return e[u].nt; }
        inline int to(int u) { return e[u].to; }
        inline int wt(int u) { return e[u].wt; }
};

const int MaxV = 1000010;
const int MaxE = 2000010;

int n;
Graph< MaxV, MaxE >G;

inline void Input() {
    read(n);
    int v, w;
    for(int u = 1; u <= n; u++) {
        read(v, w);
        G.AddEdge(u, v, w);
        G.AddEdge(v, u, w);
    }
}

int onCir[MaxV], vis[MaxV], vise[MaxE];
int Cir[MaxV], tot;

ll dis[MaxV];

bool GetCircle(int u, int fa) {
    // cout << u << '\n';
    vis[u] = 1;
    for(int i = G.head(u); i; i = G.nt(i)) {
        int v = G.to(i);
        if(vise[i]) continue;
        if(i & 1) vise[i] = vise[i + 1] = 1;
        else vise[i] = vise[i - 1] = 1;
        // cout << u << ' ' << v << endl;
        if(vis[v]) {
            onCir[u] = 1; Cir[++tot] = u;
            dis[0] = G.wt(i);
            return true;
        }
        if(GetCircle(v, u)) {
            onCir[u] = 1; Cir[++tot] = u;
            dis[tot] = dis[tot - 1] + G.wt(i);
            return true;
        }
    }
    return false;
}

pair<ll , ll > Lp[MaxV];
ll dmt[MaxV];

void GetDiameter(int u, int fa) {
    Lp[u] = make_pair(0, 0);
    for(int i = G.head(u); i; i = G.nt(i)) {
        int v = G.to(i);
        if(onCir[v]) continue;
        if(v == fa) continue;
        GetDiameter(v, u);
        if(Lp[v].first + G.wt(i) > Lp[u].first) {
            Lp[u].second = Lp[u].first;
            Lp[u].first = Lp[v].first + G.wt(i);
        }
        else if(Lp[v].first + G.wt(i) > Lp[u].second) {
            Lp[u].second = Lp[v].first + G.wt(i);
        }
        dmt[u] = max(dmt[u], dmt[v]);
    }
    dmt[u] = max(dmt[u], Lp[u].first + Lp[u].second);
}

ll ans;

/*

no repet : 
a[i] + a[j] + (dis[j] - dis[i])
a[i] - dis[i] + a[j] + dis[j]

is repet : 
a[i] + a[j] + dis[n] - (dis[j] - dis[i])
a[i] + dis[i] + dis[n] + a[j] - dis[j]

*/

ll dis2[MaxE];

inline void CalcCircle() {
    // cout << dis[0] << endl;
    // for(int i = 1; i <= tot; i++) {
    //     cout << Cir[i] << " : " << dis[i] << endl;
    // }
    ll mx = Lp[Cir[1]].first - dis[1];
    for(int i = 2; i <= tot; i++) {
        ans = max(ans, Lp[Cir[i]].first + dis[i] + mx);
        // cout << Cir[i] << ' ' << Lp[Cir[i]].first + dis[i] + mx << endl;
        mx = max(mx, Lp[Cir[i]].first - dis[i]);
    }
    dis[0] += dis[tot];
    mx = Lp[Cir[1]].first + dis[1] + dis[0];
    for(int i = 2; i <= tot; i++) {
        ans = max(ans, Lp[Cir[i]].first - dis[i] + mx);
        // cout << Cir[i] << ' ' << Lp[Cir[i]].first << ' ' << dis[i] << ' ' << mx << endl;
        mx = max(mx, Lp[Cir[i]].first + dis[i] + dis[0]);
    }
}

inline void Work() {
    ll res = 0;
    for(int i = 1; i <= n; i++) {
        if(vis[i]) continue;
        tot = 0; ans = 0;
        GetCircle(i, i);
        // cout << endl;
        for(int u = 1; u <= tot; u++) {
            GetDiameter(Cir[u], Cir[u]);
            ans = max(ans, dmt[Cir[u]]);
            // cout << Cir[u] << " : " << dmt[Cir[u]] << endl;
        }
        CalcCircle();
        res += ans;
    }
    printf("%lld\n", res);
}

int main() {
    int T = 1;
    while(T--) {
        Input();
        Work();
    }
    return 0;
}
2024/12/13 22:39
加载中...