通道:http://codeforces.com/contest/505/problem/D
题意:构造N个点M条边可达的最少边数。
思路:如果没有环且只有一个联通块,答案肯定是N-1,可知,如果没有环,那么答案肯定是N-(联通块个数),如果有环,自然要再加一条边,so,.答案是N-联通块个数+环个数。
代码:
import java.text.DecimalFormat; import java.util.*; import java.io.*; import java.math.BigInteger; public class Main { public static void main(String[] args) { InputStream inputStream = System.in; OutputStream outputStream = System.out; Reader in = new Reader(inputStream); PrintWriter out = new PrintWriter(outputStream); Solve solver = new Solve(); solver.solve(1, in, out); out.close(); } } class Solve { public void solve(int testNumber, Reader in, PrintWriter out) { int n = in.nextInt(); int m = in.nextInt(); ArrayList<Integer>[] adj = new ArrayList[n]; for(int x = 0; x < adj.length; x++) { adj[x] = new ArrayList<Integer>(); } int[] degree = new int[n]; DisjointSet ds = new DisjointSet(n); int components = n; for(int y = 0; y < m; y++) { int a = in.nextInt() - 1; int b = in.nextInt() - 1; adj[a].add(b); degree[b]++; if(ds.union(a, b)) { components--; } } ArrayDeque<Integer> queue = new ArrayDeque<Integer>(); for(int z = 0; z < degree.length; z++) { if(degree[z] == 0) { queue.add(z); } } boolean[] visited = new boolean[n]; while(queue.size() > 0) { int node = queue.remove(); visited[node] = true; for(int next : adj[node]) { degree[next]--; if(degree[next] == 0) { queue.add(next); } } } HashSet<Integer> hs = new HashSet<Integer>(); for(int a = 0; a < visited.length; a++) { if(!visited[a]) { hs.add(ds.find(a)); } } out.println(n - components + hs.size()); } static class DisjointSet { int[] parent; int[] rank; public DisjointSet(int n) { parent = new int[n]; rank = new int[n]; for(int i = 0; i < parent.length; i++) { parent[i] = i; } } public int find(int x) { if(parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } public boolean union(int x, int y) { int a = find(x); int b = find(y); if(a == b) { return false; } else { if(rank[a] < rank[b]) { parent[a] = b; } else if(rank[a] > rank[b]) { parent[b] = a; } else { parent[b] = a; rank[a]++; } return true; } } } } class Reader { private BufferedReader in; private StringTokenizer st; public Reader(InputStream is) { in = new BufferedReader(new InputStreamReader(is)); } public String next() { try { while (st == null || !st.hasMoreTokens()) { st = new StringTokenizer(in.readLine()); } return st.nextToken(); } catch (IOException e) { throw new RuntimeException(e); } } public int nextInt() { return Integer.parseInt(next()); } }