• P1453 城市环路


    基环树的最大独立集

    正解就是从环上找相邻两点s,t,求出分别以s和t为根,求max(dp[s][0],dp[t][0])

    这就是答案。因为s和t不能同时选,那只要有一个不选就行。

    我的解法是单独求基环树上的点。。。。。很捞

    我的写法

    #include<iostream>
    #include<string>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 2e5 + 11;
    vector<int>G[maxn];
    void insert(int be, int en) {
    	G[be].push_back(en);
    }
    stack<int>s;
    vector<int>ins;
    
    ll list[maxn];
    int vis[maxn];
    int dfs1(int x, int fa) {
    	if (vis[x]) {
    		if (ins.size() != 0) return 0;
    		while (s.size()) {
    			int a = s.top();
    			s.pop();
    			ins.push_back(a);
    			if (a == x) break;
    		}
    		return 0;
    	}
    	vis[x] = 1;
    	s.push(x);
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (p == fa) continue;
    		dfs1(p, x);
    	}
    	if (s.size()) s.pop();
    	return 0;
    }
    ll dp[maxn][3];
    
    int dfs(int x, int fa) {
    	dp[x][1] = list[x];
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (p == fa || vis[p]) continue;
    		dfs(p, x);
    		dp[x][1] += dp[p][0];
    		dp[x][0] += max(dp[p][0], dp[p][1]);
    	}
    	return 0;
    }
    ll chal[maxn][3];
    
    
    int main() {
    	int n;
    	cin >> n;
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld", &list[i]);
    	}
    	for (int i = 0; i < n; i++) {
    		int be, en;
    		scanf("%d %d", &be, &en);
    		be++, en++;
    		insert(be, en);
    		insert(en, be);
    	}
    	double k;
    	scanf("%lf", &k);
    
    	dfs1(1, -1);
    
    	for (int i = 1; i <= n; i++) vis[i] = 0;
    	for (int i = 0; i < ins.size(); i++) vis[ins[i]] = 1;
    
    	for (int i = 0; i < ins.size(); i++) {
    		int root = ins[i];
    		dfs(root, -1);
    	}
    	ll ans = 0;
    	//开头必选
    	chal[ins[0]][1] = dp[ins[0]][1];
    	chal[ins[0]][0] = 0;
    	int len = ins.size();
    
    	for (int i = 1; i < ins.size(); i++) {
    		int x = ins[i];
    		int p = ins[i - 1];
    		chal[x][0] = dp[x][0];
    		chal[x][1] = dp[x][1];
    
    		chal[x][0] += max(chal[p][1], chal[p][0]);
    		chal[x][1] += chal[p][0];
    	}
    	ans = max(chal[ins[len - 1]][0], ans);//开头选,结尾不能选
    
    	//开头不选
    	chal[ins[0]][1] = 0;
    	chal[ins[0]][0] = dp[ins[0]][0];
    
    	for (int i = 1; i < ins.size(); i++) {
    		int x = ins[i];
    		int p = ins[i - 1];
    
    		chal[x][0] = dp[x][0];
    		chal[x][1] = dp[x][1];
    
    		chal[x][0] += max(chal[p][1], chal[p][0]);
    		chal[x][1] += chal[p][0];
    	}
    	int root = ins[len - 1];
    
    	ans = max(ans, chal[root][0]);
    	ans = max(ans, chal[root][1]);
    	double a = 1.0*ans * k;
    	printf("%.1lf
    ", a);
    	return 0;
    }
    

      

    题解的写法

    #include<iostream>
    #include<string>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 2e5 + 11;
    vector<int>G[maxn];
    void insert(int be, int en) {
    	G[be].push_back(en);
    }
    
    vector<int>ins;
    
    ll list[maxn];
    int vis[maxn];
    int ss, tt;
    
    int dfs1(int x,int fa) {
    	if (vis[x]) {
    		if (ss == 0 && tt == 0) {
    			ss = x;
    			tt = fa;
    		}
    		return 0;
    	}
    	vis[x] = 1;
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (p == fa) continue;
    		dfs1(p, x);
    	}
    	return 0;
    }
    
    ll dp[maxn][3];
    
    int dfs(int x, int fa) {
    	dp[x][1] = list[x];
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (p == fa) continue;
    		if (x == ss && p == tt) continue;
    		if (x == tt && p == ss) continue;
    
    		dfs(p, x);
    		dp[x][1] += dp[p][0];
    		dp[x][0] += max(dp[p][0], dp[p][1]);
    	}
    	return 0;
    }
    ll chal[maxn][3];
    
    
    int main() {
    	int n;
    	cin >> n;
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld", &list[i]);
    	}
    	for (int i = 0; i < n; i++) {
    		int be, en;
    		scanf("%d %d", &be, &en);
    		be++, en++;
    		insert(be, en);
    		insert(en, be);
    	}
    
    	double k;
    	scanf("%lf", &k);
    	dfs1(1, -1);
    	ll ans = 0;
    
    	dfs(ss, -1);
    	ans = max(dp[ss][0], ans);
    	
    	for (int i = 1; i <= n; i++) dp[i][0] = dp[i][1] = 0;
    
    	dfs(tt, -1);
    	ans = max(dp[tt][0], ans);
    
    	double a = 1.0*ans*k;
    	printf("%.1lf
    ", a);
    	return 0;
    }
    

      

  • 相关阅读:
    算符优先分析
    自下而上语法分析
    递归下降语法分析
    LL(1)文法的判断,递归下降分析程序
    消除左递归
    4.K均值算法--应用
    2.机器学习相关数学基础
    K均值算法
    机器学习概述
    算符优先分析
  • 原文地址:https://www.cnblogs.com/lesning/p/14082943.html
Copyright © 2020-2023  润新知