2024年4月10日-暑期实习-第三题(300分)-公网下线方案

在线评测链接

题目描述

公有云的某个region内, N N N个网络节点组网情况可以使用一个 n × n n\times n n×n的矩阵matrix表示,在这个组网图中, m a t r i x [ i ] [ j ] = p matrix[i][j]=p matrix[i][j]=p时,表示用户在编号为 i i i的节点访问编号为 j j j的节点时,必须在 i i i节点上具有 ≥ p \ge p p的权限等级(p=0 时表示无法通过 i i i节点访问 j j j节点),如果用户成功访问了j节点,那么它在 j j j节点上的权限等级调整为 p p p
exposed为一个整数数组,表示暴露在公网上的网络节点的编号列表。某天扫描发现这批暴露在公网的节点存在被外部恶意攻击风险,且该攻击会影响到可访问的其他节点,并可以持续传递进行攻击。被恶意攻击的节点从公网访问时,攻击者获得了ROOT权限(权限等级为10,即最大值)。
塔子哥是一名网络安全工程师,为了在有限的时间内尽可能的减少故障带来的损失,需要立即将某个节点从公网"下线"。
假设攻击结束时,被攻击过的节点数量为 R R R,请帮塔子哥计算出将哪个节点下线能使R尽可能小,如果答案有多个节点,返回索引最小的那个节点。请注意:从公网“下线”的节点,不会受到来自公网的攻击,但仍然可能被“可访问"的其他节点传递攻击。

输入描述

输入的第一行是网络节点数量 N N N
后续的 N N N行,每行 N N N个数字v,以空格分割,形成一个 N × N N\times N N×N的矩阵,表示网络节点组网的矩阵。
最后一行,输入exposed数组,表示暴露在公网上的网络节点的编号列表数组元素不会重复。

2 ≤ N ≤ 24 2\le N\le 24 2N24

0 ≤ v ≤ 10 0\le v\le 10 0v10

0 ≤ e x p o s e d [ i ] ≤ N − 1 0\le exposed[i]\le N-1 0exposed[i]N1

输出描述

输出在 exposed 数组中,计划“下线"的那个节点的编号。

样例1

输入

4
1 0 0 0
0 1 2 0
0 1 1 4
0 0 3 1
1 3

输出

3

说明

1,3是公网暴露的节点
1,2,3三个节点是连通的,但相互访问需要考虑权限等级限制,例如从1节点登录,访问到2节点后,权限等级不足以访问3号节点
如果将1号节点从公网下线,那3号节点可以先访问2号在访问1号,此时R的值为3。如果将3号节点从公网下线,则只能通过1号节点访问到2号节点,而2号节点无法再访问3号节点,此时R的值为2,答案选择R值更小的公网节点下线方案,因此答案为3.

题目思路

考虑暴力dfs,先将暴露的节点按编号从小到大排序,考虑下线每个暴露的节点,下线之后从其它暴露节点开始dfs,赋予权限10,最后统计一下被攻击的节点数量。被攻击节点数量最少对应的下限节点就是答案。

注意由于可能所有情况节点都会被攻击,所以幸存的节点数量初始化应该为-1。

代码

C++

#include <bits/stdc++.h>
using namespace std;

int n,m;
int a[25][25];
int exposed[11];
int book[25],cnt[25];
int mx=-1,id;

void dfs(int x,int p){
        book[x]=true;
        cnt[x]++;
        for(int j=0;j<n;++j){
                if(a[x][j]&&!book[j]&&p>=a[x][j]){
                        dfs(j,min(p,a[x][j]));
                }
        }
}

void check(int x){
        for(int i=0;i<m;++i){
                if(exposed[i]==x) continue;
                memset(book,0,sizeof book);
                dfs(exposed[i],10);
        }
        int res=n;
        for(int i=0;i<n;++i){
                if(cnt[i]){
                        res--;
                }
        }
        if(res>mx){
                mx=res;
                id=x;
                
        }
}

int main(){
        //freopen("test.in","r",stdin);
        std::ios::sync_with_stdio(false);
        cin>>n;
        for(int i=0;i<n;++i){
                for(int j=0;j<n;++j){
                        cin>>a[i][j];
                }
        }
        while(cin>>exposed[m]){
                m++;
        }
        sort(exposed, exposed + m);
        for(int i=0;i<m;++i){
                memset(cnt,0,sizeof cnt);
                check(exposed[i]);
        }
        cout<<id;

        return 0;
}
  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值