小欧占领了其中一些城市。如果两个城市可以通过若干条道路互相到达,且这些道路经过的城市都是小欧占领的,那么这两个城市之间就可以通过经商获得收益
现在,小欧准备占领一个未被占领的城市,使得总收益最大化。你能帮帮她吗?
第一行输入两个正整数和
,代表城市数量和道路数量。
第二行输入一个长度为的 01 串。第
个字符为'0'代表小欧未占领该城市,'1'代表小欧占领了该城市。
接下来的行,每行输入两个正整数
和
,代表城市
和城市
有一条道路连接。
输出两个整数,第一个整数代表占领的城市编号,第二个整数代表占领后的收益。请保证收益的最大化。如果有多种方案收益最大,请输出占领编号最小的城市。
5 5 01010 1 2 1 3 1 4 4 5 1 5
1 3
占领 1 号城市后,总收益为 3。1 号城市和 2 号城市经商,1 号城市和 4 号城市经商,2 号城市和 4 号城市经商。
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { static int[] fa, size; static int find(int x) { return x == fa[x] ? x : (fa[x] = find(fa[x])); } static void union(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) return; if (size[fx] < size[fy]) { size[fy] += size[fx]; fa[fx] = fy; } else { size[fx] += size[fy]; fa[fy] = fx; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(); sc.nextLine(); fa = new int[n + 1]; size = new int[n + 1]; for (int i = 1; i <= n; i++) { fa[i] = i; size[i] = 1; } String occ = sc.nextLine(); char[] chs = occ.toCharArray(); List<Integer>[] G = new ArrayList[n + 1]; for (int i = 1; i <= n; i++) G[i] = new ArrayList<>(); for (int i = 0; i < m; i++) { int u = sc.nextInt(), v = sc.nextInt(); G[u].add(v); G[v].add(u); if (chs[u - 1] == '1' && chs[v - 1] == '1') union(v, u); } long ans = 0; boolean[] used = new boolean[n + 1]; for (int u = 1; u <= n; u++) { int f = find(u); if (used[f]) continue; used[f] = true; ans += (long) size[f] * (size[f] - 1) / 2; } // System.out.println(ans); long maxProfit = 0; int idx = -1; Arrays.fill(used, false); for (int u = 1; u <= n; u++) { if (chs[u - 1] == '0') { long curProfit = 0, pref = 1; for (int v : G[u]) { int f = find(v); if (chs[v - 1] == '0' || used[f]) continue; used[f] = true; curProfit += pref * size[f]; pref += size[f]; } for (int v : G[u]) { int f = find(v); if (chs[v - 1] == '0' || !used[f]) continue; used[f] = false; } if (curProfit > maxProfit) { maxProfit = curProfit; idx = u; } } } System.out.println(idx + " " + (ans + maxProfit)); } }