ディレクトリリンク:
Likouプログラミングの質問-ソリューションの概要-共有+記録-CSDNブログ
GitHub同期ブラッシングプロジェクト:
https://github.com/September26/java-algorithms
オリジナルタイトルリンク:フォースバックル
説明:
0からn-1までの番号が付けられたn台のサーバーを備えたコンピューターネットワークが与えられます。同時に、2D整数配列エッジが与えられます。ここで、edges [i] = [ui、vi]は、サーバーuiとviの間にメッセージラインがあり、サーバーuiとviの間で任意の数のメッセージを転送できることを意味します。 2番目。長さnの別の整数配列の忍耐力と0から始まる添え字を提供します。
タイトルは、すべてのサーバーが接続されていることを保証します。つまり、任意のサーバーから開始されたメッセージが、これらの情報行を介して直接または間接的に他のサーバーに到達できることを保証します。
0の番号が付けられたサーバーはマスターサーバーであり、他のサーバーはデータサーバーです。各データサーバーはマスターサーバーに情報を送信し、応答を待ちます。メッセージはサーバー間で最適にルーティングされます。つまり、各メッセージは最短時間でメインサーバーに到着します。メインサーバーは、新しく到着したすべてのメッセージを処理し、各メッセージの送信元のルートとは反対の方向にすぐに応答を送信します。
0秒の開始時に、すべてのデータサーバーが処理に必要な情報を送信します。各データサーバーは、最初の1秒から開始し、各秒の開始時に、マスターサーバーから応答メッセージ(新しく送信されたメッセージの応答メッセージを含む)を受信したかどうかを確認します。
応答メッセージが受信されていない場合、サーバーは定期的にメッセージを再送信します。データサーバーiは、patience [i]秒ごとにメッセージを再送信します。つまり、データサーバーiは、最後にプライマリサーバーにメッセージを送信してからpatience[i]秒後にプライマリサーバーにメッセージを再送信します。
それ以外の場合、データサーバーはメッセージを再送信しません。
情報が有線で送信されないか、サーバーに到達しない場合、コンピューターネットワークはアイドル状態になります。
コンピュータネットワークがアイドル状態になる最も早い秒数を返してください。
例1:
入力:edges = [[0,1]、[1,2]]、patience = [0,2,1]
出力:8
説明:
0秒の開始時に、
-データサーバー1はマスターサーバーにメッセージを送信します(1A Expressを使用)。
-データサーバー2は、マスターサーバーにメッセージを送信します(2Aで示されます)。
1秒で、
-メッセージ1Aがメインサーバーに到着すると、メインサーバーはメッセージ1Aをすぐに処理し、1Aの応答メッセージを送信します。
-データサーバー1はまだ応答を受信していません。最後のメッセージが送信されてから1秒が経過したため(1 <patience [1] = 2)、メッセージは再送されません。
-データサーバー2はまだ応答を受信していません。最後のメッセージが送信されてから1秒が経過したため(1 == patience [2] = 1)、メッセージを再送信します(2Bで示されます)。
2秒で、
-応答メッセージ1Aがサーバー1に到着し、サーバー1はメッセージを再送信しません。
-メッセージ2Aがメインサーバーに到着すると、メインサーバーはメッセージ2Aをすぐに処理し、2Aの応答メッセージを送信します。
-サーバー2はメッセージを再送信します(2Cで示されます)。
...
4秒で、
-応答メッセージ2Aがサーバー2に到着し、サーバー2はメッセージを再送信しません。
...
7秒で、応答メッセージ2Dがサーバー2に到着します。
8秒以降、サーバー間で情報が送信されなくなり、サーバーに情報が到達しなくなります。
したがって、8秒は、ネットワークがアイドル状態になる最も早い瞬間です。
例2:
入力:edges = [[0,1]、[0,2]、[1,2]]、patience = [0,10,10]
出力:3
説明:データサーバー1および2は、 2秒の情報。
3秒目から、ネットワークはアイドル状態になります。
ヒント:
n == patience.length
2 <= n <= 105
patience [0] == 0
for 1 <= i <n、1 <= patience [i] <= 105
1 <= edges.length <= min(105、 n *(n-1)/ 2)
edges [i] .length == 2
0 <= ui、vi <n
ui!=vi
には重複するエッジはありません。
各サーバーは、他のサーバーに直接または間接的に接続されています。
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/the-time-when-the-network-becomes-idle
著作権はLeetcodeNetworkに帰属します。商用の再版については、公式の承認に連絡してください。非商用の再版については、出典を示してください。
問題解決のアイデア:
*問題解決のアイデア: *まず、0で到達できるノードのセットを見つけ、次にこのセットに1ステップで到達できます。 *次に、このセットを通じて、到達可能なこのセット内の番号、つまり2つのステップで再帰的に到達できる番号を探し、到達可能なすべての番号を見つけます。 *次に、1ステップ、2ステップ、3ステップのセットを見つけ、各番号に費やした時間を見つけます。 *費やした時間は3つのケースに分けられます。 *1:忍耐の時間は往復時間以上であり、この時点で往復時間は2*ステップで使用できます。 * 2:往復時間は忍耐の時間の倍数に正確に等しく、費やされる時間は次のとおりです:2 *ステップ+(2 *ステップ/時間-1)*時間 * 3:往復時間は忍耐の時間の倍数に等しくありません。これに費やされる時間は次のとおりです。2*ステップ+(2 *ステップ/時間)*時間 *ここで、2*ステップ/時間は待機するサイクル数を表します。
コード:
public class Solution2039 {
// public int networkBecomesIdle(int[][] edges, int[] patience) {
// int n = patience.length;
// List<Integer>[] adj = new List[n];
// for (int i = 0; i < n; ++i) {
// adj[i] = new ArrayList<Integer>();
// }
// boolean[] visit = new boolean[n];
// for (int[] v : edges) {
// adj[v[0]].add(v[1]);
// adj[v[1]].add(v[0]);
// }
//
// Queue<Integer> queue = new ArrayDeque<Integer>();
// queue.offer(0);
// visit[0] = true;
// int dist = 1;
// int ans = 0;
// while (!queue.isEmpty()) {
// int size = queue.size();
// for (int i = 0; i < size; i++) {
// int curr = queue.poll();
// for (int v : adj[curr]) {
// if (visit[v]) {
// continue;
// }
// queue.offer(v);
// int time = patience[v] * ((2 * dist - 1) / patience[v]) + 2 * dist + 1;
// ans = Math.max(ans, time);
// visit[v] = true;
// }
// }
// dist++;
// }
// return ans;
// }
public int networkBecomesIdle(int[][] edges, int[] patience) {
Set<Integer> allSet = new HashSet<>();
Set<Integer>[] sets = new Set[patience.length];
for (int i = 0; i < patience.length; i++) {
if (i != 0) {
allSet.add(i);
}
sets[0] = new HashSet<>();
}
for (int[] ints : edges) {
int i1 = ints[0];
int i2 = ints[1];
Set<Integer> integers1 = sets[i1];
if (i2 > 0) {
integers1.add(i2);
}
Set<Integer> integers2 = sets[i2];
if (i1 > 0) {
integers2.add(i1);
}
}
Map<Integer, Set<Integer>> levelMap = new HashMap<>();
search(1, levelMap, allSet, sets[0], sets);
System.out.println(levelMap.size());
int max = 0;
for (int step : levelMap.keySet()) {
Set<Integer> integers = levelMap.get(step);
for (int index : integers) {
int time = patience[index];
int minTime = step * 2;
if (minTime <= time) {
//使用stepTime
max = Math.max(minTime, max);
continue;
}
if ((step * 2) % time == 0) {
max = Math.max(2 * step + (2 * step / time - 1) * time, max);
continue;
}
max = Math.max(2 * step + (2 * step / time) * time, max);
}
}
return max + 1;
}
private void search(int level, Map<Integer, Set<Integer>> levelMap, Set<Integer> allSet, Set<Integer> set, Set<Integer>[] sets) {
levelMap.put(level, set);
allSet.removeAll(set);
Set<Integer> newSet = new HashSet<>();
for (Integer i : set) {
Set<Integer> integers = sets[i];
if (integers == null) {
continue;
}
for (Integer value : integers) {
if (allSet.contains(value)) {
newSet.add(value);
allSet.remove(value);
}
}
}
if (newSet.size() == 0) {
return;
}
search(level + 1, levelMap, allSet, newSet, sets);
}
}