这道题我做过类似的,但是还是不太会做,真是太菜了

(个人感觉牛客的每日一题挺好,我好多不会的,hhh)


其实这题也不会,看的别的大佬的思路写的,树形DP,感觉很好(最小割的话还是不会的,过段时间去学习下)

题目要求找度数为1的点(除了s), 然后要求我们让他不能到达s,那么我们就切除当前点与到s路径上边权最小的点即可,但是我就想为什么需要 f[] += min() 呢,想到一个特殊情况
4 4 1
1 2 1
2 3 1
2 4 1

这种情况我们切除 1 - 2 就可以,所以我们需要 += 去判断最小值。

然后dfs去搜索,标记好他的当前节点和父节点即可,然后求出f[s] 的最小值。


#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 100010, M = 200010, INF = 0x3f3f3f3f;

int h[N], e[M], ne[M], d[N], w[M], f[N], idx;

int n, m, s;

void add(int x, int y, int z){
    e[idx] = y, w[idx] = z, ne[idx] = h[x], h[x] = idx ++;
}

void dfs(int u, int p){
    if (d[u] == 1 && u != s){
        f[u] = INF;
        return ;
    }
    for (int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];
        if (j != p){
            dfs(j, u);
            f[u] += min(f[j], w[i]);
        }
    }
}

int main(){

    scanf("%d%d%d",&n,&m,&s);

    memset(h, -1, sizeof h);

    for (int i = 0; i < m; i++){
        int x, y, z;
        scanf("%d%d%d",&x,&y,&z);
        add(x, y, z), add(y, x, z);
        d[x]++, d[y]++;
    }

    dfs(s,0);

    printf("%d\n",f[s]);

    return 0;
}