zoukankan      html  css  js  c++  java
  • 牛客nc22598 Rinne Loves Edges

    题目链接:https://ac.nowcoder.com/acm/problem/22598

    简单题意:给定一棵有边权的树和一个点S,删去一些边使得所有的叶子和S不连通。求删去的最小边权和

    可以把S看做根。f[i]表示使得i的子树上的叶子和i不连通,删去的最小边权和。则有f[i]=Σmin(f[j],dis[i][j]),其中j是i的子结点。这题的n<=1e6,不能直接用dis数组存边权,可以用邻接表顺便存下来。最后答案就是f[s]

    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    using namespace std;
    
    const int maxn=1e5+10;
    struct st{int ver,w;}; 
    vector<st> g[maxn];
    int t,n,m,s,i,j,k,vis[maxn];
    ll f[maxn];
    
    void dp(int u){
    	vis[u]=1; int num=0; 
    	for (int i=0;i<g[u].size();i++) //判断叶子 
    	  if (vis[g[u][i].ver]==0) num++;
    	if (num==0) f[u]=1e10;
    	for (int i=0;i<g[u].size();i++){
    	  int k=g[u][i].ver; //子节点 
    	  if (vis[k]) continue;
    	  dp(k);
    	  if (f[k]>g[u][i].w) f[u]+=g[u][i].w;else f[u]+=f[k]; 
    	}
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&s);
    	for (i=1;i<n;i++){
    	  int x,y,w; st e;
    	  scanf("%d%d%d",&x,&y,&w); e.w=w;
    	  e.ver=x; g[y].pb(e);
    	  e.ver=y; g[x].pb(e);
    	}
    	dp(s);
    	printf("%lld
    ",f[s]);
    	return 0;
    }
    

      

    一道类似的题:牛客nc210473

    题目链接:https://ac.nowcoder.com/acm/problem/210473

    简单题意:删去一些边,使得叶子和根节点1不连通。求删去的边权和<=m的情况下,其中最大边权的最小值

    要求最小的最大值,考虑二分答案mid,然后用上一题的树形dp来判断最大值为mid的情况下,结果f[1]和m的关系即可。注意做树形dp的时候如果边权>mid就不能删掉这个边,只能删掉子树

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
     
    vector<int> g[1010];
    int n,m,i,l,r,mid,d[1010][1010],vis[1010],f[1010];
     
    void dp(int u){
        vis[u]=1; int num=0;
        for (int i=0;i<g[u].size();i++)
          if (!vis[g[u][i]]) num++;
        if (num==0) f[u]=1e6;
        for (int i=0;i<g[u].size();i++){
          int k=g[u][i];
          if (vis[k]) continue;
          dp(k);
          if (d[u][k]>mid) f[u]+=f[k]; else f[u]+=min(f[k],d[u][k]);
        }
    }
     
    int main(){
        cin>>n>>m;
        for (i=1;i<n;i++){
          int x,y,dis;
          cin>>x>>y>>dis;
          g[x].pb(y);g[y].pb(x);
          d[x][y]=d[y][x]=dis;
        }
        l=0;r=1e3+10;
        while (l<r-1){
          memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f));
          mid=(l+r)/2; dp(1);
          if (f[1]>m) l=mid; else r=mid;
        }
        if (r==1e3+10) cout<<-1<<endl; else cout<<r<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    SqlSugar ORM 入门篇2 【查询】 让我们实现零SQL
    .NET ORM框架 SqlSugar4.0 功能快速预览【开源】
    Django 2 by example
    持续为您导航
    Django框架
    Python快速入门
    第一章 创建博客应用
    Python术语对照表
    49、你并不了解的format、decimal
    48、python内存泄露
  • 原文地址:https://www.cnblogs.com/edmunds/p/13497758.html
Copyright © 2011-2022 走看看