题意:原本一颗无根树,以s为根结点拉起,求这颗树中任意叶子结点都不可到达s的最小代价
dp[u]表示以u为根的子树中的所有叶子结点都到达不了u的最小代价
①u是叶子结点时dp[u] = inf;
②其余 dp[u]:for(int v : son[u]){ dp[u] += min(dp[v],edge(u,v));}
对于叶子结点无法做到自己不可达自己,而对于其他结点u要么令叶子结点不可达u的子节点,要么自己断去子节点的边(另外忘了无向图边数乘2,一直RE。。。。。。)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 1e5+10; const ll inf = 1e18; int n,m,s,idx; int head[N],in[N]; ll dp[N]; struct Edge{ int to,nex; ll w; }e[N]; void addedge(int u,int v,ll w){ e[idx].to = v; e[idx].nex = head[u]; e[idx].w = w; head[u] = idx++; } void dfs(int u,int fa){ if(in[u] == 1&&u!=s){ dp[u] = inf; return; } for(int i = head[u];~i;i = e[i].nex){ int v = e[i].to; if(v == fa) continue; dfs(v,u); dp[u]+=min(dp[v],e[i].w); } } int main(){ scanf("%d%d%d",&n,&m,&s); memset(head,-1,sizeof(head)); for(int i = 0;i < m;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); addedge(u,v,w);addedge(v,u,w); in[u]++,in[v]++; } dfs(s,-1); printf("%lld\n",dp[s]); return 0; }