给出一个图 G(V,E) ,图上有 n 个点,m 条边,所有的边都是无向边。
最开始,也就是第 0 天的时候,这 n 个点中有一个点 v 感染了病毒,之后的每一天,凡是感染病毒的点都会向它的邻居点传播病毒。经过了 t 天之后,得到了感染病毒的点集 S 。要求找出第 0 天感染病毒的点 v 。如果 v 有很多不同的答案,把它们都找出来。
数据范围: , ,
给出一个图 G(V,E) ,图上有 n 个点,m 条边,所有的边都是无向边。
第一行两个数n,m,接下来有m行,每行两个数u,v,表示点u,v之间有一条无向边。接下来一行两个数k,t,其中k表示集合S的大小。最后一行k个数,集合S中的元素。输入的图可能有自环和重边,输入保证S中的数互不相同。
输出一行,如果不存在这样的v,输出-1。
否则输出所有可能的v,按照从小到大的顺序输出,数字之间用空格隔开,不要在行末输出多余的空格。
4 3 3 2 1 2 1 4 3 2 4 2 1
4
第0天,第1天,第2天感染病毒的点如图
import java.util.LinkedList; import java.util.HashSet; public class Main/*VirusTransmission2*/ { final static int INF = 0x3f3f3f3f; public static void main(String[] args) { java.util.Scanner sc = new java.util.Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(), i, t, inNum, flg; int[][] G = new int[n][n]; boolean[] infected = new boolean[n], ans = new boolean[n]; HashSet<Integer>[] adj = new HashSet[n]; LinkedList<Integer> q = new LinkedList<>(); boolean[] visited = new boolean[n]; for (i = 0; i < n; ++i) { adj[i] = new HashSet<>(); java.util.Arrays.fill(G[i], INF); G[i][i] = 0; } for (i = 0; i < m; ++i) { int u = sc.nextInt() - 1, v = sc.nextInt() - 1; if (u != v) { adj[u].add(v); adj[v].add(u); } } inNum = sc.nextInt(); t = sc.nextInt(); for (i = 0; i < inNum; ++i) { int j = sc.nextInt() - 1; infected[j] = ans[j] = true; } for (i = 0; i < n; ++i) { java.util.Arrays.fill(visited, false); visited[i] = true; q.clear(); q.add(i); while (!q.isEmpty()) { int cur = q.pop(); for (Integer a : adj[cur]) { if (!visited[a]) { G[i][a] = G[i][cur] + 1; q.add(a); visited[a] = true; } } } } for (i = 0; i < n; ++i) { if (infected[i]) { for (int j = 0; j < n; ++j) { if (infected[j] && G[i][j] > t) ans[i] = ans[j] = false; else if (!infected[j] && G[i][j] <= t) ans[i] = false; } } } for (flg = i = 0; i < n; ++i) { if (ans[i]) { System.out.printf("%s%d", flg == 0 ? "" : " ", i+1); flg = 1; } } System.out.println(flg == 0 ? "-1" : ""); } }
#include <iostream> #include <vector> #include <deque> #include <algorithm> #include <unistd.h> using namespace std; bool breadth_first_search_algorithm(vector<vector<int>>& g, const int n, const int start, const int t, vector<int>& s) { vector<int> seen(n + 1); deque<int> q{{start}}; seen[start] = 1; // mark as seen int days = 0; vector<int> v; // 经过了t天之后,得到了感染病毒的点集 v while (not q.empty() && days <= t) { size_t s = q.size(); while (s--) { const int cur = q.front(); q.pop_front(); v.emplace_back(cur); for (const int nei : g[cur]) { if (seen[nei]) continue; q.emplace_back(nei); seen[nei] = 1; } } ++days; } sort(begin(v), end(v)); return v == s; }; void printAnswer(vector<int>& ans) { for (auto iter = begin(ans); iter != end(ans); ++iter) { cout << *iter; if (iter < end(ans) - 1) cout << ' '; } cout << endl; } int main(void) { // test 时间挑站 usleep(1E6 - 1000 * 100); int n, m; cin >> n >> m; vector<vector<int>> g(n + 1); while (m--) { int u, v; cin >> u >> v; g[u].emplace_back(v); g[v].emplace_back(u); } int k, t, x; cin >> k >> t; vector<int> s; // s 集合 while (k--) { cin >> x; s.emplace_back(x); } std::sort(begin(s), end(s)); vector<int> ans; for (int u = 1; u <= n; ++u) if (breadth_first_search_algorithm(g, n, u, t, s)) ans.emplace_back(u); if (ans.empty()) cout << -1 << endl; else printAnswer(ans); return 0; }
#include <bits/stdc++.h> using namespace std; bool S[1001]; vector<int> G[1001]; int n, t; bool BFS(int x) { int vis[1001]; memset(vis, 0, sizeof(vis)); queue<int> q; vis[x] = 1; q.push(x); int u; while (!q.empty()) { u = q.front(); q.pop(); if (vis[u] > t) break; for (auto &v: G[u]) { if (vis[v] == 0) { vis[v] = vis[u] + 1; q.push(v); } } } for (int i = 1; i <= n; i++) { if (!S[i] && vis[i] != 0) return false; if (S[i] && vis[i] == 0) return false; } return true; } int main() { int m, u, v, cnt = 0; scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } int s, k; scanf("%d%d", &k, &t); for (int i = 1; i <= k; i++) { scanf("%d", &s); S[s] = true; } for (int i = 1; i <= n; i++) { if(BFS(i)){ cnt++; if(cnt==1) printf("%d", i); else printf(" %d", i); } } if (cnt == 0) printf("-1"); printf("\n"); return 0; }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.LinkedList; /** * @author wylu */ public class Main { //感染病毒的点为true, 未感染的为false static boolean[] infected; static ArrayList<Integer>[] graph; static int n, m, k, t; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] strs = br.readLine().split(" "); n = Integer.parseInt(strs[0]); m = Integer.parseInt(strs[1]); infected = new boolean[n + 1]; graph = new ArrayList[n + 1]; for (int i = 1; i <= n; i++) graph[i] = new ArrayList<>(); //建图 for (int i = 0; i < m; i++) { strs = br.readLine().split(" "); int u = Integer.parseInt(strs[0]), v = Integer.parseInt(strs[1]); graph[u].add(v); graph[v].add(u); } strs = br.readLine().split(" "); k = Integer.parseInt(strs[0]); t = Integer.parseInt(strs[1]); for (String s : br.readLine().split(" ")) { infected[Integer.parseInt(s)] = true; } int res = 0; for (int i = 1; i <= n; i++) { if (infected[i] && bfs(i)) { System.out.print((res++ > 0 ? " " : "") + i); } } System.out.println((res == 0) ? "-1" : ""); } //以x为起点传播t天的结果和实际结果比较是否相同 private static boolean bfs(int x) { //每个点被传染需要的时间, 为0表明没有被传染 int[] cost = new int[n + 1]; LinkedList<Integer> queue = new LinkedList<>(); cost[x] = 1; queue.offer(x); while (!queue.isEmpty()) { int cur = queue.poll(); if (cost[cur] > t) break; for (Integer e : graph[cur]) { if (cost[e] == 0) { cost[e] = cost[cur] + 1; queue.offer(e); } } } for (int i = 1; i <= n; i++) { if (!infected[i] && cost[i] != 0) return false; if (infected[i] && cost[i] == 0) return false; } return true; } }
from collections import defaultdict n, m = map(int, input().split()) # n个点,m条边 d = defaultdict(set) # 用d存储图,用set去重 for _ in range(m): p1, p2 = map(int, input().split()) d[p1].add(p2) d[p2].add(p1) k, t = map(int, input().split()) # s大小为k,共t天 s = set(map(int, input().split())) # s为最终感染情况 res = [] def check(v): # BFS搜索,检查v点在t天后感染情况是否与符合要求 q = [v] infected = set([v]) # infected记录已经感染的地区 for i in range(t): if not q: break for j in range(len(q)): # 每天找出新增的感染地区 tmp = q.pop(0) for node in d[tmp]: if node not in infected: q.append(node) infected.add(node) if infected == s: # 如果感染情况与s一致,说明v符合要求,加入res res.append(v) for v in s: # 遍历s中每个点,检查是否符合要求 check(v) if not res: print(-1) else: print(' '.join(list(map(str,res))))
bfs 模拟
import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.Scanner; /** * @author zxy */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(); // 构建图,点的范围在 [1:n] HashSet[] edges = new HashSet[n + 1]; for (int i = 0; i < edges.length; i++) { edges[i] = new HashSet(); } for (int i = 0; i < m; i++) { int a = sc.nextInt(), b = sc.nextInt(); // 去自环 if (a != b) { edges[a].add(b); edges[b].add(a); } } // 填充 infection 集合 int k = sc.nextInt(), t = sc.nextInt(); HashSet infection = new HashSet(); for (int i = 0; i < k; i++) { infection.add(sc.nextInt()); } // bfs 找起点 ArrayList res = new ArrayList(); for (int i = 1; i <= n; i++) { if (bfs(edges, t, infection, i)) { res.add(i); } } // 输出 if (res.size() == 0) { System.out.println(-1); } else { for (int i = 0; i < res.size() - 1; i++) { System.out.print(res.get(i)); System.out.print(' '); } System.out.print(res.get(res.size() - 1)); } } // 层序遍历 private static boolean bfs(HashSet[] edges, int t, HashSet infection, int start) { HashSet visited = new HashSet(); LinkedList queue = new LinkedList(); if (infection.contains(start)) { queue.offer(start); visited.add(start); } int days = 0; while (!queue.isEmpty()) { for (int i = queue.size(); i > 0; i--) { Integer poll = queue.poll(); for (Integer next : edges[poll]) { if (!infection.contains(next)) { return false; } else if (!visited.contains(next)) { visited.add(next); queue.offer(next); } } } if (++days == t) { break; } } return visited.size() == infection.size(); } }
import collections edges = set() n, m = map(int, input().split()) # 去除边中的自环和重边,对于边(x, y) # 若x == y则该边是自环,若(y, x)已在集合edges中,则(x, y)是重边 for _ in range(m): x, y = map(int, input().split()) if x != y and not (y, x) in edges: edges.add((x, y)) k, t = map(int, input().split()) nodes = list(map(int, input().split())) # 建图 adj = collections.defaultdict(list) for edge in edges: x, y = edge adj[x].append(y) adj[y].append(x) # BFS res = [] for node in nodes: queue = [] visited = [0]*(n+1) queue.append(node) visited[node] = 1 # h是感染的天数 h, infected = 0, [] infected.append(node) while queue and h < t: tmp = [] while queue: nod = queue.pop() for neighbor in adj[nod]: if not visited[neighbor]: tmp.append(neighbor) visited[neighbor] = 1 h += 1 queue = tmp infected += tmp # t天结束后,若被感染的点集合infected和nodes中的点相同,则node是一个感染起点 if sorted(infected) == sorted(nodes): res.append(node) # 输出结果 n = len(res) if n == 0: print(-1) res.sort() for i in range(n - 1): print(res[i], end=' ') print(res[-1])各位大佬能帮忙看下我这段代码逻辑哪里出错了吗?一直是50%(python3)
病毒传播
暴力寻找每个被感染的点是否是起点v。对于每个起点v,广度优先遍历扩散一遍,扩散后结果和S集相同,则v是可能结果。
import java.util.*; public class Main { static boolean bfs(Set<Integer>[] g, int n, int x, boolean[] infected, int t, int k) { LinkedList<Integer> q = new LinkedList<>(); Set<Integer> set = new HashSet<>();//存当前扩散到的点 q.offer(x); set.add(x); int distance = 0;// 记录是第几天扩散到点 while(!q.isEmpty()) { int size = q.size(); distance ++; if(distance > t) break;// 超过t天,不需要继续了 for(int i=0; i < size; i++) { int cur = q.poll(); for(int v : g[cur]) { if(set.contains(v)) continue;//已经被访问,直接跳过 if(infected[v] == false) { return false; //以x为起点,扩散到v,但实际v未被感染,因此,x一定非起点 } q.offer(v); set.add(v); } } } //当t天后,扩散到的点刚好为k个时,符合题意。否则x一定不是起点 if(set.size() == k) return true; return false; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(); Set<Integer>[] g = new HashSet[n+1]; // 去除重边 for(int i=1; i <= n; i++) g[i] = new HashSet<Integer>(); for(int i=0; i < m; i++) { int u = sc.nextInt(), v = sc.nextInt(); if(u != v) { //去除自环 g[u].add(v); g[v].add(u); } } int k =sc.nextInt(), t = sc.nextInt(); boolean[] infected = new boolean[n+1]; List<Integer> res = new ArrayList<>(); for(int i=0; i < k; i++) { int v = sc.nextInt(); infected[v] = true; } for(int i=1; i <= n; i++) { // 暴力找起点 if(infected[i] && bfs(g, n, i, infected, t, k)) res.add(i); } if(res.size() == 0) { System.out.println("-1"); } else { for(int i=0; i < res.size()-1; i++) System.out.print(res.get(i)+" "); System.out.println(res.get(res.size()-1)); } } }
import sys from collections import deque if __name__ == "__main__": line = raw_input() lines = line.split() n = int(lines[0]) m = int(lines[1]) edges = [] for i in range(m): line = raw_input() lines = line.split() edges.append([int(lines[0]), int(lines[1])]) line = raw_input() lines = line.split() k = int(lines[0]) t = int(lines[1]) S = [] line = raw_input() lines = line.split() for item in lines: S.append(int(item)) V = set(range(1,n+1)) infected = set(S) noninfect = V - infected infected = list(infected) noninfect = list(noninfect) adjList = {} for idx in range(1,n+1): adjList[idx] = [] for i in range(len(edges)): if edges[i][1] not in adjList[edges[i][0]] and edges[i][1] != edges[i][0]: adjList[edges[i][0]].append(edges[i][1]) if edges[i][0] not in adjList[edges[i][1]] and edges[i][1] != edges[i][0]: adjList[edges[i][1]].append(edges[i][0]) visited = [0 for i in range(n+1)] graph = [[sys.maxint for i in range(n+1)] for j in range(n+1)] for i in range(1,n+1): graph[i][i] = 0 result = [] for item in infected: depth = 1 visited = [0 for i in range(n+1)] stack = [] stack1 = [] stack.append(item) visited[item] = 1 while True: tmp = stack.pop() for node in adjList[tmp]: if visited[node]==0 and node>=1 and node<=n: stack1.append(node) visited[node] = 1 if(graph[item][node]>depth): graph[item][node] = depth if len(stack) == 0: stack = stack1 stack1 = [] depth += 1 if len(stack) == 0: break flag = 0 for jtem in noninfect: if graph[item][jtem] <= t: flag = 1 break for ktem in infected: if graph[item][ktem] >t: flag = 1 break if flag == 0: result.append(item) result.sort() string = [] for item in result: string.append(str(item)) if len(result) == 0: print -1 else: print " ".join(string)