【图论】Codeforce 505D Mr. Kitayuta's Technology

通道: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());
    }
}

 

posted @ 2015-01-28 16:02  mithrilhan  阅读(338)  评论(0编辑  收藏  举报