• [Codeforces440D]Berland Federalization


    Problem

    给你一棵树,最少删掉哪些边,能使得余下的至少有1个大小刚好为k的残树。
    1 ≤ k ≤ n ≤ 400

    Solution

    用f[i][j]表示以i为根有j个节点的最少删边数量
    因为此题要输出删除的边
    v[i][j]表示以i为根删掉j个节点需要删去的边对应的(点u,该u点还需要删去的边数量)

    Notice

    因为要输出方案,所以比较复杂

    Code

    #include<cmath>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define sqz main
    #define ll long long
    #define reg register int
    #define rep(i, a, b) for (reg i = a; i <= b; i++)
    #define per(i, a, b) for (reg i = a; i >= b; i--)
    #define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
    typedef pair<int, int> Node;
    const int INF = 1e9, N = 400;
    const double eps = 1e-6, phi = acos(-1.0);
    ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
    ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
    void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
    struct node
    {
    	int vet, next;
    }edge[N + 5];
    int head[N + 5], num = 0, f[N + 5][N + 5], Flag[N + 5], fa[N + 5], n, k;
    vector<Node> v[N + 5][N + 5];
    void add(int u, int v)
    {
    	edge[++num].vet = v;
    	edge[num].next = head[u];
    	head[u] = num;
    }
    void dfs(int u)
    {
        rep(i, 0, k) f[u][i] = INF;
        f[u][1] = 0;
    	travel(i, u)
    	{
    		int vv = edge[i].vet;
    		if (vv == fa[u]) continue;
    		fa[vv] = u;
    		dfs(vv);
    		per(j, k, 0)
    		{
    			f[u][j]++;
    			rep(t, 0, j)
                    if (f[u][j - t] + f[vv][t] < f[u][j])
                    {
                        f[u][j] = f[u][j - t] + f[vv][t];
                        v[u][j].clear();
                        v[u][j].assign(v[u][j - t].begin(), v[u][j - t].end());
                        v[u][j].push_back(make_pair(vv, t));
                    }
    		}
    	}
    }
    void Out(int u, int now)
    {
        Flag[u] = 1;
        for (auto i : v[u][now]) Out(i.first, i.second);
        travel(i, u)
            if (!Flag[edge[i].vet]) printf("%d ", (i + 1) / 2);
    }
    int sqz()
    {
    	n = read(), k = read();
    	rep(i, 1, n) head[i] = 0;
    	rep(i, 1, n - 1)
    	{
    		int u = read(), v = read();
    		add(u, v), add(v, u);
    	}
    	dfs(1);
    	int ans = f[1][k], root = 1;
    	rep(i, 2, n)
    		if (f[i][k] + 1 < ans) ans = f[i][k] + 1, root = i;
    	printf("%d
    ", ans) ;
    	if (ans) Out(root, k);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    蓝桥杯省赛经验
    阅读笔记四
    阅读笔记二
    阅读笔记一
    动态规划——Maximum Sum of 3 Non-Overlapping Subarrays
    动态规划——Remove Boxes
    动态规划——Dungeon Game
    动态规划——Freedom Trail
    动态规划——Frog Jump
    《软件需求十步走》阅读笔记一
  • 原文地址:https://www.cnblogs.com/WizardCowboy/p/7689868.html
Copyright © 2020-2023  润新知