首页 > 其他分享 >环图问题

环图问题

时间:2023-09-08 17:45:03浏览次数:37  
标签:const int res ++ dfs 问题 环图 include

环图由一些简单的链和环组成。

对于有向图,所有点入度与出度 <= 2,就是一个环图

对于无向图,所有点的度数 <= 2,就是一个环图

环图中所有的链与环互不相交。

常见问题:环的大小,个数,路径

 

 

 

 这种无序变有序的问题,建图方法:把起点向终点连一条边。每个点入度出度都是1,所以建成的图中只存在若干简单环和自环。

目标是将图中的所有环变为n个自环,最少操作 n - m次。

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

using namespace std;

const int N = 5e5 + 10;

string str;
int a[N], b[N], idx;

int main() {
    cin >> str;
    
    int n = str.size();
    int s[3] = {0};
    for(int i = 0; i < n; i ++ ) {
        if(str[i] == 'L') a[i] = 0;
        else if(str[i] == 'M') a[i] = 1;
        else a[i] = 2;
        s[a[i]] ++ ;
    }
    
    for(int i = 0; i < 3; i ++ ) {
        for(int j = 0; j < s[i]; j ++ ) {
            b[idx ++ ] = i;
        }
    }
    
    int e[3][3] = {0};
    for(int i = 0; i < n; i ++ ) {
        e[a[i]][b[i]] ++ ;   //建图,为若干有向环
    }
    
    int m = 0;
    for(int i = 0; i < 3; i ++ ) {
        m += e[i][i];    //加上自环数量,
    }
    
    for(int i = 0; i < 3; i ++ ) {
        for(int j = i + 1; j < 3; j ++ ) {
            int t = min(e[i][j], e[j][i]);  //加上小环数量
            m += t, e[i][j] -= t, e[j][i] -= t; //删除小环
        }
    }
    
    m += e[0][1] + e[1][0];  //小环删除后只剩下大环,正向或反向
    
    cout << n - m << endl;
    
    return 0;
}

 

与题目一思路相同的一道题:

 

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

using namespace std;

const int N = 1010;

int n;
int a[N], b[N], idx;

int main() {
    cin >> n;
    
    int s[4] = {0};
    for(int i = 0; i < n; i ++ ) {
        cin >> a[i];
        s[a[i]] ++ ;
    }
    
    for(int i = 1; i <= 3; i ++ ) {
        for(int j = 0; j < s[i]; j ++ ) {
            b[idx ++ ] = i;
        }
    }
    
    int e[4][4] = {0};
    for(int i = 0; i < n; i ++ ) {
        e[a[i]][b[i]] ++ ;
    }
    
    int m = 0;
    for(int i = 1; i <= 3; i ++ ) m += e[i][i];
    
    for(int i = 1; i <= 3; i ++ ) {
        for(int j = i + 1; j <= 3; j ++ ) {
            int t = min(e[i][j], e[j][i]);
            m += t, e[i][j] -= t, e[j][i] -= t;
        }
    }
    
    m += e[1][2] + e[2][1];
    
    cout << n - m << endl;
    
    return 0;
}

 

 

 

 建图方式:起点向变换点连边。

要求每个点所在环的大小 -> 并查集。

 

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

using namespace std;

const int N = 2e5 + 10;

int n;
int p[N], s[N], a[N];

int find(int x) {
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main() {
    
    int T;
    scanf("%d", &T);
    while(T -- ) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i ++ ) p[i] = i, s[i] = 1;
        
        for(int i = 1; i <= n; i ++ ) {
            int pa = find(i), pb = find(a[i]);
            if(pa != pb) {
                s[pb] += s[pa];
                p[pa] = pb;
            }
        }
        
        for(int i = 1; i <= n; i ++ ) cout << s[find(i)] << ' ';
        cout << endl;
    }
    
    return 0;
}

 

 

建图方式:将每个点分为上半和下半两个点,把能互相连通的点连边。

这一题目有涉及到了方向变化问题,遇到此类问题,我们就将所有方向按顺时针从0开始编号,按题意找规律即可。

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

using namespace std;

const int N = 1010;

int n, m;
char g[N][N];

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

int dfs(int x, int y, int d) {
    if(x < 0 || x >= n || y < 0 || y >= m) return 0;
    
    if(g[x][y] == '/') d ^= 1;
    else d ^= 3;
    
    return dfs(x + dx[d], y + dy[d], d) + 1;
}

int main() {
    scanf("%d%d", &n, &m);
    
    for(int i = 0; i < n; i ++ ) {
        for(int j = 0; j < m; j ++ ) {
            cin >> g[i][j];
        }
    }
    
    int res = 0;
    for(int i = 0; i < n; i ++ ) {
        res = max(res, dfs(i, 0, 1));
        res = max(res, dfs(i, m - 1, 3));
    }
    
    for(int i = 0; i < m; i ++ ) {
        res = max(res, dfs(0, i, 2));
        res = max(res, dfs(n - 1, i, 0));
    }
    
    cout << res << endl;
    
    return 0;
}

 

 

 建图方式:起点向终点连边。

我们要找环的个数和最大环的点数。

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

using namespace std;

const int N = 110;

int n;
int a[N], b[N], p[N], s[N];

int find(int x) {
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main() {
    cin >> n;
    
    int cnt = 0, sz = -1;
    
    for(int i = 1; i <= n; i ++ ) p[i] = i, s[i] = 1;
    
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    for(int i = 1; i <= n; i ++ ) cin >> b[i];
    
    
    for(int i = 1; i <= n; i ++ ) {
        int pa = find(a[i]), pb = find(b[i]);
        if(pa != pb) {
            s[pb] += s[pa];
            p[pa] = p[pb];
        }
    }
    
    for(int i = 1; i <= n; i ++ ) {
        if(a[i] == find(a[i]) && a[i] != b[i]) {
            cnt ++ ;
            sz = max(sz, s[a[i]]);
        }
    }
    
    cout << cnt << ' ' << sz << endl;
    
    return 0;
}

 

标签:const,int,res,++,dfs,问题,环图,include
From: https://www.cnblogs.com/zk6696/p/17687198.html

相关文章

  • 【Ps小问题集合】
    (Ps小问题集合)一、小问题1.1Ps将图片裁剪成圆的首先打开ps,打开需要进行裁剪的图片选择右侧的椭圆选框工具按着shift可以进行圆形的绘制,不按shift则会是椭圆绘制完成后,按着ctrl+j键,新建图层,即可在右侧图层栏新建一图层,图层内容为刚刚选中的部分,将最开始的图层的眼睛选择......
  • 25 生产者消费者问题:利用缓冲区:管程法
    packageThreadDemo;//生产者消费者问题:利用缓冲区:管程法//wait()令自己等待,notify()唤醒别的线程publicclassTest25_Producer_Consumer_1{publicstaticvoidmain(String[]args){SynBuffersynBuffer=newSynBuffer();newConsumer(synB......
  • python3 postgreSQL 依赖问题
    unabletoexecute'gcc':NosuchfileordirectoryItappearsyouaremissingsomeprerequisitetobuildthepackagefromsource.Youmayinstallabinarypackagebyinstalling'psycopg2-binary'fromPyPI.Ifyouwantto......
  • nvm有下载版本,切换版本成功,node -v还是切换前的版本问题解决
    是因为在下载nvm之前,电脑中的node版本已经存在了,所以需要将之前的node版本全部清楚干净!卸载node之前请node-v查看一下现在的版本,记住这个版本,切记切记!!!!!控制面板中卸载node.;卸载已安装过的NVM;没装过NVM的就仅仅卸载node去环境变量里面看一下有没有跟nvm和node相关的东西了,有的话全......
  • 昇腾实践丨ATC模型转换动态shape问题案例
    本文分享自华为云社区《ATC模型转换动态shape问题案例》,作者:昇腾CANN。ATC(AscendTensorCompiler)是异构计算架构CANN体系下的模型转换工具:它可以将开源框架的网络模型(如TensorFlow等)以及AscendIR定义的单算子描述文件转换为昇腾AI处理器支持的离线模型;模型转换过程中,ATC会进行......
  • EasyCVR国标视频综合管理平台:解决磁盘爆满问题的有效方法
    EasyCVR国标视频综合管理平台是一款以视频为核心的智慧物联应用平台。它基于分布式、负载均衡等流媒体技术进行开发,提供广泛兼容、安全可靠、开放共享的视频综合服务。该平台具备多种功能,包括视频直播、录像、回放、检索、云存储、告警上报、语音对讲、集群、智能AI分析以及平台级......
  • 国标GB28181视频监控EasyGBS接入大量通道时,创建角色接口未响应的问题解决方法
    EasyGBS是一款基于国标GB28181协议的视频云服务平台。它支持多路设备同时接入,并能将视频流以RTSP、RTMP、FLV、HLS、WebRTC等格式分发到多个平台和终端。该平台提供了视频监控直播、云端录像、云存储、检索回放、智能告警、语音对讲、平台级联等功能。在视频能力方面,GB28181视频监......
  • RTSP流媒体协议视频平台EasyNVR新版存在跨域问题的原因排查
    针对客户反馈的TSINGSEE青犀视频全线产品存在的跨域问题,以前的版本确实遇到过这类问题。目前,我们在服务器端已经进行了允许跨域的配置。然而,仍然有一些客户可能会遇到类似的问题。在本文中,我们将介绍我们采用的解决方法。我们测试了其他浏览器,都是可以获取数据的:我们注意到存在跨域......
  • Linux软件安装与依赖问题
    apt与yum大部分时间,在Linux发行版中安装软件使用的是apt(Ubuntu),yum(CentOS)。这两个软件都是高级的软件包管理工具,在使用它们安装软件的时候,会自动解决软件包的依赖关系,可以从指定的软件库获取软件包和其依赖项,并自动进行下载、安装、更新。rpm与dpkg它们都用于直接操作软件包......
  • openpyxl使用问题——OSError: File contains no valid workbook part
    第一种:打开xls的文件,报错,这个比较容易理解,就是openpyxl是不支持打开xls文件的,版本太老了。推荐使用xlrd库。openpyxl.utils.exceptions.InvalidFileException:openpyxldoesnotsupporttheold.xlsfileformat,pleaseusexlrdtoreadthisfile,orconvertittothemo......