1 solutions

  • 0
    @ 2025-5-23 16:21:17

    90分代码,最后一个点TLE。我已经找到原因了,希望有同学也能找到。

    然后希望大家能总结出代码T的常见原因,增加比赛实战经验。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N = 1e6 + 10;
    LL f[N][2], ans;
    vector<int> g[N];
    int p[N]; // 战斗力
    // fa[i]:骑士i痛恨的人
    // 虽然很想把自己痛恨的人当作儿子,但做到后面就会发现
    // 还是存成基环外向树,在DP的时候比较好处理
    int fa[N];
    int n;
    bool vis[N]; // 要找环,所以得加vis
    
    int x; // 环上断开的边的一个端点
    void dfs(int u) {
    	// 在“没有上司的舞会”代码基础上,要多记录几个状态
    	vis[u] = 1;
    	f[u][0] = 0;
    	f[u][1] = p[u];
    	for (int v : g[u]) {
    		// 只有环边端点x会被重复访问一次
    		if (v == x) continue;
    		dfs(v);
    		f[u][0] += max(f[v][0], f[v][1]);
    		f[u][1] += f[v][0];
    	}
    }
    
    // 解决点u所在基环树的问题
    void solve(int u) {
    	// 找环,锁定环上的一条边 (x,y)
    	x = u;
    	while (fa[x] && !vis[fa[x]]) {
    		x = fa[x];
    		vis[x] = 1;
    		// cout << x << "\n";
    	}
    	dfs(x);
    	// 保证x不被选中,那么x的fa就可以被选中
    	// 在DP里写起来更方便(与保证x一定被选相比))
    	LL t = f[x][0];
    	// 然后从断边的另一个端点进入DFS
    	x = fa[x];
    	dfs(x);
    	ans += max(t, f[x][0]);
    }
    
    int main() {
    	ios::sync_with_stdio(0), cin.tie(0);
    	cin >> n;
    	int v;
    	for (int i = 1; i <= n; i++) {
    		cin >> p[i] >> v;
    		g[v].push_back(i);
    		fa[i] = v;
    	}
    
    	for (int i = 1; i <= n; i++)
    		if (!vis[i]) solve(i);
    
    	cout << ans;
    
    	return 0;
    }
    
  • 1

Information

ID
164
Time
1000ms
Memory
512MiB
Difficulty
9
Tags
# Submissions
56
Accepted
6
Uploaded By