首页 > 其他分享 >déce. 28 两道题

déce. 28 两道题

时间:2022-12-28 18:57:13浏览次数:58  
标签:连通 ch int 28 ce while long 两道 getchar

https://www.luogu.com.cn/problem/P2820

菜题一天做一道还是太浪费时间了

最小生成树,输入数据保证边权为正
但是原始图可能不连通,生成树要保证图的不连通性
问题不大,建立"超级父亲"就行了(假,见注)

不对,求最小生成树不会加原本没有的边,所以不会更改原图的连通性
所以最终选上的边数肯定会小于\(n-1\)
但是不能用\(n-[连通块个数]\)来决定选边终止的时候(假)
可以用,还是连通性与并查集的问题:一个块一旦连通,这个块就不能再加边了

不用\(n-[连通块个数]\)决定选边的代码

#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef long long ll;

int in{
    int i=0,f=1; char ch=0;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') f=-1, ch=getchar();
    while('0'<=ch&&ch<='9') i=(i<<1)+(i<<3)+ch-48, ch=getchar();
    return i*f;
}

const int N=1e4+5;
int n,m,cnt,fa[N],supfa,tot,revans;
struct edge{
    int u,v,w;
    edge(){};
    edge(int U,int V,int W){u=U,v=V,w=W;}
    friend bool operator < (const edge &a, const edge &b){return a.w<b.w;}
}e[N];

inline int get(int x){ return fa[x]==x?x:fa[x]=get(fa[x]);}

int main(){

    // freopen("1.in","r",stdin);

    n=in,m=in; supfa=n;
    for(int i=1;i<=n;++i) fa[i]=i;
    for(int i=1;i<=m;++i){
        int u=in,v=in,w=in;
        e[i]=edge(u,v,w);
        tot+=w;
    }

    sort(e+1,e+m+1);

    for(int i=1;i<=m;++i){
        int u=get(e[i].u), v=get(e[i].v);
        if(u==v) continue;
        fa[u]=v;
        revans+=e[i].w;
    }

    printf("%d\n",tot-revans);
    return 0;
    
}

利用\(n-[连通块个数]\)优化的代码

#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef long long ll;

int in{
    int i=0,f=1; char ch=0;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') f=-1, ch=getchar();
    while('0'<=ch&&ch<='9') i=(i<<1)+(i<<3)+ch-48, ch=getchar();
    return i*f;
}

const int N=1e4+5;
int n,m,cnt,fa[N],supfa,tot,revans,block;
struct edge{
    int u,v,w;
    edge(){};
    edge(int U,int V,int W){u=U,v=V,w=W;}
    friend bool operator < (const edge &a, const edge &b){return a.w<b.w;}
}e[N];

inline int get(int x){ return fa[x]==x?x:fa[x]=get(fa[x]);}

int main(){

    // freopen("1.in","r",stdin);

    n=in,m=in; supfa=n;
    for(int i=1;i<=n;++i) fa[i]=i;
    for(int i=1;i<=m;++i){
        int u=in,v=in,w=in;
        e[i]=edge(u,v,w);
        tot+=w;
        u=get(u),v=get(v);
    }

    sort(e+1,e+m+1);
    sort(fa+1,fa+n+1);
    for(int i=1;i<=n;++i) if(fa[i]^fa[i-1]) ++block;
    for(int i=1;i<=n;++i) fa[i]=i;

    for(int i=1;i<=m;++i){
        int u=get(e[i].u), v=get(e[i].v);
        if(u==v) continue;
        ++cnt;
        fa[u]=v;
        revans+=e[i].w;
        if(cnt==n-block) break;
    }

    printf("%d\n",tot-revans);
    return 0;
    
}

注:上面所说的超级父亲,只是一种预处理所有连通块,然后分块求最小生成树的办法,不太好写
预处理所有连通块,然后让连通块中的节点都指向一个”超级父亲“(序号大于\(n\))

https://www.luogu.com.cn/problem/P1991

第一眼:老二分答案了
第二眼:似乎不需要二分答案,按边权从大到小选装卫星电话的哨所就行了
第三眼:还是要二分答案啊,对于每个答案,求连通块个数,连通块个数\(<S\)的合法

但这雀食不优,而且WA3个点qwq
剩下的明天de,今天肝不动了(该死的新冠qwq)

de出来了,原先用并查集计算连通块个数的方法错了
利用每次合并操作减少一个连通块得到最终的连通块个数

#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef long long ll;

int in{
    int i=0,f=1; char ch=0;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') f=-1, ch=getchar();
    while('0'<=ch&&ch<='9') i=(i<<1)+(i<<3)+ch-48, ch=getchar();
    return i*f;
}

const int N=600;
const double eps=1e-4;
int s,p,cnt,fa[N],block;
struct node{
    double x,y;
}d[N];
struct edge{
    int u,v;
    double w;
    edge(){};
    edge(int uu,int vv,double ww){ u=uu, v=vv, w=ww;}
    friend bool operator < (const edge &a, const edge &b){ return a.w<b.w;}
}e[N*N];
double l,r=2e8;

double Dist(const node &a, const node &b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int get(int x){ return fa[x]==x?x:fa[x]=get(fa[x]);}

bool check(double mid){
    for(int i=1;i<=p;++i) fa[i]=i; block=p;
    for(int i=1;i<=cnt;++i){
        if(e[i].w>mid+eps) break;
        int u=get(e[i].u), v=get(e[i].v);
        if(u==v) continue;
        fa[u]=v; --block;
    }
    // printf("%d %lf\n",block,mid);
    return block<=s;
}

int main(){ 

    // freopen("1.in","r",stdin);

    s=in, p=in;
    for(int i=1;i<=p;++i) d[i].x=in, d[i].y=in;
    for(int i=1;i<=p;++i)
        for(int j=i+1;j<=p;++j)
            e[++cnt]=edge(i,j,Dist(d[i],d[j]));
    
    sort(e+1,e+cnt+1);

    while(r-l>eps){
        double mid=(l+r)/2;
        if(check(mid)) r=mid;
        else l=mid;
    }

    printf("%.2lf\n",r);
    return 0;
    
}

当然还有更好的方法:
从小到大加边,会遇到两种情况

  1. 再加入一条边使连通块个数从\(s+1\)变成\(s\),设此边长\(d_1\);
  2. 再加入一条边使连通块个数从\(s\)变成\(s-1\),设此边长\(d_2\)。

在\(d_1, d_2\)之间的边长都合法
要求最短边,那就取\(d_1\)

然后这题就随手切了

#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef long long ll;

int in{
    int i=0,f=1; char ch=0;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') f=-1, ch=getchar();
    while('0'<=ch&&ch<='9') i=(i<<1)+(i<<3)+ch-48, ch=getchar();
    return i*f;
}

const int N=600;
int s,p,fa[N],block,cnt;
struct node{ int x,y;}d[N];

struct edge{
    int u,v;
    double dis;
    edge(){};
    edge(int uu,int vv,double ddis){ u=uu, v=vv, dis=ddis;}
    friend bool operator < (const edge &a, const edge &b){ return a.dis<b.dis;}
}e[N*N];

double dis(int u,int v){ return sqrt((d[u].x-d[v].x)*(d[u].x-d[v].x)+(d[u].y-d[v].y)*(d[u].y-d[v].y));}
int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}

int main(){

    // freopen("1.in","r",stdin);

    s=in, p=in;
    for(int i=1;i<=p;++i) fa[i]=i; block=p;
    for(int i=1;i<=p;++i)
        d[i].x=in, d[i].y=in;
    
    for(int i=1;i<=p;++i)
        for(int j=i+1;j<=p;++j)
            e[++cnt]=edge(i,j,dis(i,j));
    
    sort(e+1,e+cnt+1);

    for(int i=1;i<=cnt;++i){
        int u=get(e[i].u), v=get(e[i].v);
        if(u==v) continue;
        fa[u]=v;
        --block;
        if(block==s){ printf("%.2lf\n",e[i].dis); return 0;}
    }
    
}

标签:连通,ch,int,28,ce,while,long,两道,getchar
From: https://www.cnblogs.com/antimony-51/p/17011037.html

相关文章

  • CentOS7.9 安装 Python3.7.9
    #安装依赖yum-yinstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-develgdbm-develdb4-devellibpcap-develxz-devell......
  • Openstack-mitakaCentos7.2双节点搭建--(一)基础服务搭建
    虚拟机准备版本Centos7.21511网络配置:管理网络:192.168.100.10controller192.168.100.20compute外部网络192.168.200.10controller192.168.200.20computeVmware......
  • AWS使用EC2降低DeepRacer的训练成本:DeepRacer-for-cloud的实践操作
    文章目录​​前言​​​​一、技术介绍​​​​二、实现途径​​​​三、效果展示​​​​AWSDeepRacer-for-Cloud安装训练脚本如下​​​​遇到的问题​​​​四、总结​......
  • Codeforces Round #841 (Div. 2) and Divide by Zero 2022
    CodeforcesRound#841(Div.2)andDividebyZero2022o(╥﹏╥)o2022的最后一场也没打好B题反正我是理解错了,我看到题目上写着要相乘再取模,结果就真的去先乘再取模,这......
  • CentOS7.2基于LAMP搭建WordPress,并自定义Logo和名称
    本次搭建LAMP+Wordpress环境如下MySQLphpWordpress_CN4.9ApacheCentOS7.2192.168.200.101、安装mariadb、php、httpd、wget2、测试php3、下载wordpress并配置4、网页......
  • cesaro sum和tauber型定理
    缓更Definition.1:Givenasequence\(\{a_n\}(n\ge1)\),thecesarosumofadenote$\lim_{n\rightarrow\infty}\frac{\sum_{i=1}^na_i}{n}$,ifthislimit......
  • 2022.12.28笔记
    1、父组件调用子组件中的方法【函数】:(1)通过ref直接调用子组件的方法;参考链接:https://www.cnblogs.com/effortandluck/p/16355992.html 2、音频属性的认识;  ......
  • centos 安装 influxdb2
       http://www.manongjc.com/detail/27-asqkkdxungikkls.html https://github.com/influxdata/influxdb/releases下载influxdb2-2.6.0.x86_64.rpm安装yumloc......
  • CentOS7.9 安装 gcc-4.8.0
    查看GCC版本号是否已满足gcc-v下载包wgethttp://mirrors.concertpass.com/gcc/releases/gcc-4.8.0/gcc-4.8.0.tar.bz2解压包tarjxvfgcc-4.8.0.tar.bz2进入......
  • SpringBoot系列之数据库初始化-datasource配置方式
    【DB系列】数据库初始化-datasource配置方式|一灰灰Blog在我们的日常业务开发过程中,如果有db的相关操作,通常我们是直接建立好对应的库表结构,并初始化对应的数据,即更......