zoukankan      html  css  js  c++  java
  • 51nod 1307 绳子与重物 二分+dfs / 并查集

    题目链接:

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307

    题意:

    题解:

    方法一:
    因为所有绳子最终组成了1棵树,所以我们可以通过一次DFS,来检测是否有某根绳子下面绑了超过他所能负荷的重量。
    具体方法:对每个节点,计算其子树的重量和(包含自身的重量),如果大于能承受的最大重量,则绳子会断,否则不会断。
    一次DFS时间复杂度是O(n)的。
    既然一次判断的复杂度是O(n)的,并且当绳子第一次断掉后,继续放重物,不会改变绳子断掉的状态(毕竟重物的重量都是正数,没有负数),那么我们可以用二分来做。
    二分来求第一次断掉的点,由于二分的复杂度是log(n),一次DFS判断的复杂度是O(n),所以整个算法的复杂度是nlog(n)。
    二分经常被用来求解一些具有单调性的问题,这里的单调性就是断掉以后,不会再次变成不断的。

    方法二:
    我们在DFS的过程中,使用并查集,将子树节点的Root指向当前节点,同时计算子树的总重量。
    假如当前节点的承重不足,那么绳子会断掉。所以我们需要去掉一些节点,来保证绳子不断。根据题目要求,我们按照子树节点的编号从高到低,逐个去掉这些重物,直到绳子不断为止。
    那么问题来了,并查集这个结构并不能解决按照编号从高到低去掉子树的问题,如果自己维护其他的数据结构(比如堆),恐怕复杂度还要多一个Log。

    所以我们跳出按照编号从高到低去掉子树的思路,不如直接从编号N - 1到0去掉子树,直到当前的绳子不断为止。 因为编号小的断了,后面再加的绳子也没有用了,已经有绳子断了就结束了。

    代码:

    二分:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 struct node{
    19     int c,w,f;
    20 }e[maxn];
    21 
    22 vector<int> g[maxn];
    23 
    24 bool book;
    25 
    26 ll dfs(int u,int k){
    27     ll sum = e[u].w;
    28     if(u > k) return 0;
    29     for(auto v : g[u])
    30         sum += dfs(v,k);
    31     if(sum > e[u].c && u) book = false;
    32     return sum;
    33 }
    34 
    35 int main(){
    36     int n=read();
    37     for(int i=1; i<=n; i++){
    38         e[i].c=read(); e[i].w=read(); e[i].f=read(); e[i].f++;
    39         g[e[i].f].push_back(i);
    40     }
    41 
    42     int l=0,r=n,ans = 0;
    43     while(l<=r){
    44         int mid = (l+r)/2;
    45         book = true;
    46         dfs(0,mid);
    47         if(book) ans=mid,l=mid+1;
    48         else r=mid-1;
    49     }
    50 
    51     cout << ans << endl;
    52 
    53     return 0;
    54 }

    并查集:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 struct node{
    19     ll c,w,f;
    20 }e[maxn];
    21 
    22 vector<int> g[maxn];
    23 int fa[maxn];
    24 ll ww[maxn];
    25 int k;
    26 
    27 int find(int x){
    28     return fa[x]==x ? x : fa[x]=find(fa[x]);
    29 }
    30 
    31 void update(int u){
    32     for(auto v : g[u]){
    33         e[u].w += e[v].w;
    34         fa[v] = u;
    35     }
    36 
    37     while(e[u].w > e[u].c){
    38         e[find(k)].w -= ww[k];
    39         k--;
    40     }
    41 }
    42 
    43 int main(){
    44     int n=read();
    45     for(int i=1; i<=n; i++){
    46         e[i].c=read(); e[i].w=read(); e[i].f=read(); e[i].f++;
    47         g[e[i].f].push_back(i); ww[i] = e[i].w;
    48         fa[i] = i;
    49     }
    50 
    51     k = n;
    52     for(int i=n; i>0; i--)
    53         update(i);
    54 
    55     cout << k << endl;
    56 
    57     return 0;
    58 }
  • 相关阅读:
    SpringMVC中静态获取request对象 Spring中获取 HttpServletRequest对象【转载】
    springcloud 的loadbalancer 轮询算法切换方法 2021.4.3
    springboot项目启动增加图标
    rabbitmq 端口作用以及修改方法
    centos8 安装rabbitmq
    springcloud config client Value获取不到信息的问题的处理方法
    springcloud config配置git作为数据源然后启动报错 If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    Sublime Text的列模式如何操作
    centos8 安装redis
    jQuery简单的Ajax调用
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827576.html
Copyright © 2011-2022 走看看