1. 程式人生 > >leetcode 928. 儘量減少惡意軟體的傳播 II(dfs或bfs)

leetcode 928. 儘量減少惡意軟體的傳播 II(dfs或bfs)

題目:

在節點網路中,只有當 graph[i][j] = 1 時,每個節點 i 能夠直接連線到另一個節點 j

一些節點 initial 最初被惡意軟體感染。只要兩個節點直接連線,且其中至少一個節點受到惡意軟體的感染,那麼兩個節點都將被惡意軟體感染。這種惡意軟體的傳播將繼續,直到沒有更多的節點可以被這種方式感染。

假設 M(initial) 是在惡意軟體停止傳播之後,整個網路中感染惡意軟體的最終節點數。

我們可以從初始列表中刪除一個節點,並完全移除該節點以及從該節點到任何其他節點的任何連線。

如果移除這一節點將最小化 M(initial), 則返回該節點。如果有多個節點滿足條件,就返回索引最小的節點。

思路:

這個題目要求的是:完全移除該節點以及從該節點到任何其他節點的任何連線,這也就是說求每個病原體單獨感染了多少節點。也就是說我們需要算出哪些節點只被一個源節點感染。然後統計一下這些節點中,哪個源節點感染次數最多。就可以找出來這個源節點。採用dfs或者bfs可以統計一個節點感染節點的個數。我們需要定義一下陣列:

flag[i]:記錄節點i的源節點(病原體節點)

fnum[i]:記錄節點i被幾個源節點感染了

num[i]:如果i為源節點,那麼記錄他感染了幾個節點,如果不是,則為0

pan[i]:快速判斷節點i是不是源節點,如果是,則置1,不是則置0.

注意,無論是dfs還是bfs,在搜尋的時候遇到另一個源節點都不能把它放搜尋隊列中。

程式碼:dfs

class Solution {
public:
int flag[305],num[305];
int pan[305],fnum[305];
void dfs(int root,int now,vector<vector<int>>& graph){
    int len = graph.size();
    for(int i=0;i<len;i++){
        if(graph[now][i]){
            if(pan[i]||flag[i]==root)continue; //如果遇到另外一個源節點或者當前節點已被當前源節點感染
            flag[i] = root;
            fnum[i]++;
            dfs(root,i,graph);
        }
    }
}

int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
    memset(flag,-1,sizeof(flag)); memset(num,0,sizeof(num)); memset(pan,0,sizeof(pan));memset(fnum,0,sizeof(fnum));
    int sz = initial.size();
    for(int i=0;i<sz;i++)pan[initial[i]] = 1;
    for(int i=0;i<sz;i++){   //對於每一個源節點都搜一下
        int root = initial[i];
        flag[root] = root;num[root] = 1;
        fnum[root]++;
        dfs(root,root,graph);
    }
    int ma = 0;int ans = 0;
    int len = graph.size();
    for(int i=0;i<len;i++){  //如果只有一個源節點感染當前節點,那麼對應的源節點單獨感染數量增加
        if(fnum[i]==1)num[flag[i]]++;
    }
    sort(initial.begin(),initial.end()); //注意排序
    for(int i=0;i<sz;i++){
        if(num[initial[i]]>ma){
            ma = num[initial[i]];ans = initial[i];
        }
    }
    return ans;
}
};

bfs:

class Solution {
public:
int flag[305],fnum[305],num[305],pan[305];

int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
    memset(flag,0,sizeof(flag));memset(fnum,0,sizeof(fnum));memset(num,0,sizeof(num));memset(pan,0,sizeof(pan));
    int sz = initial.size();
    int len = graph.size();
    for(int i=0;i<sz;i++){
        pan[initial[i]] = 1;
    }
    for(int i=0;i<sz;i++){
        queue<int>q;
        int root = initial[i];
        flag[root] = root;fnum[root] = 1;
        q.push(root);
        while(!q.empty()){
            int now = q.front();q.pop();
            for(int j=0;j<len;j++){
                if(graph[now][j]){
                    if(pan[j]||flag[j]==root)continue;
                    flag[j] = root;
                    fnum[j]++;
                    q.push(j);
                }
            }
        }

    }
    for(int i=0;i<len;i++){
        if(fnum[i]==1)num[flag[i]]++;
    }
    sort(initial.begin(),initial.end());
    int ma = 0,ans = -1;
    for(int i=0;i<sz;i++){
        if(num[initial[i]]>ma){
            ma = num[initial[i]];ans = initial[i];
        }
    }
    return ans;
}

};

思路都是相同的。主要是想通了斷掉所有連線其實就是找由這個病原體單獨感染的節點數目。