1. 程式人生 > >CCF-CSP 通訊網路 JAVA 201709-4 100分

CCF-CSP 通訊網路 JAVA 201709-4 100分

思路:

我不知道標準解法是怎麼樣的,反正我為我“禁忌的解法”解得100分感到很開心=。=

首先使用list,製作好圖的鄰接表。

一個是

1→2→3

2→4

3→4

4

一個是

1

2→1

3→1

4→2→3

為什麼要分兩個鄰接表呢,因為一個鄰接表不能正確的表示我們要的結果。(自己體悟吧。。。  表1確定傳送訊號方有哪些全知,表2確定接受訊號方有哪些全知)

接下來我們做一個n*n(為去掉0實際n+1 * n+1)的二維陣列 vis

vis[i][j] 表示 點i和點j是否可以連通

最終只要j從1到n都為true(都連通) 則部門i全知,ans++

那麼下面實際操作:只需要用bfs或者dfs做一下這個vis表就可以了

package csp2017_09_4;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;

public class Main{
	static List<Integer> list[];
	static List<Integer> list2[];
	static boolean vis [][] ;
	static boolean vn[];
	static int n,m;
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		list = new ArrayList[n+1];
		list2 = new ArrayList[n+1];
		for (int i = 0; i < list.length; i++) {
			list[i] = new ArrayList<Integer>();
			list2[i] = new ArrayList<Integer>();
		}
		for (int i = 0; i < m; i++) {
			int s = sc.nextInt();
			int e = sc.nextInt();
			list[s].add(e);
			list2[e].add(s);
		}
		vis = new boolean[n+1][n+1];
		for (int i = 0; i < vis.length; i++) {
			vis[i][i] = true;
		}
		
		//bfs
		Queue<Integer> q = new LinkedList();
		for (int t = 1; t <= n; t++) {
			q.add(t);
			vn = new boolean[n+1];
			while(!q.isEmpty()){
				int temp = q.poll();
				if(!vn[temp]){
					for (int i = 0; i < list[temp].size(); i++) {
						int next = list[temp].get(i);
						q.add(next);
					}
					vn[temp] = true;
					vis[t][temp] = true;
				}
			}
		}
		for (int t = 1; t <= n; t++) {
			q.add(t);
			vn = new boolean[n+1];
			while(!q.isEmpty()){
				int temp = q.poll();
				if(!vn[temp]){
					for (int i = 0; i < list2[temp].size(); i++) {
						int next = list2[temp].get(i);
						q.add(next);
					}
					vn[temp] = true;
					vis[t][temp] = true;
				}
			}
		}
		
//		for (int i = 1; i < vis.length; i++) {
//			for (int j = 1; j < vis[i].length; j++) {
//				if(vis[i][j])System.out.print(1+" ");
//				else System.out.print(0+" ");
//			}
//			System.out.println();
//		}
		
		
		int ans = 0;
		for (int i = 1; i < vis.length; i++) {
			boolean knowAll = true;
			for (int j = 1; j < vis[i].length; j++) {
				if(!vis[i][j]){knowAll = false;break; }
			}
			if(knowAll) ans++;
		}
		System.out.println(ans);
	}

}


問題描述
試題編號: 201709-4
試題名稱: 通訊網路
時間限制: 1.0s
記憶體限制: 256.0MB
問題描述: 問題描述   某國的軍隊由N個部門組成,為了提高安全性,部門之間建立了M條通路,每條通路只能單向傳遞資訊,即一條從部門a到部門b的通路只能由ab傳遞資訊。資訊可以通過中轉的方式進行傳遞,即如果a能將資訊傳遞到bb又能將資訊傳遞到c,則a能將資訊傳遞到c。一條資訊可能通過多次中轉最終到達目的地。
  由於保密工作做得很好,並不是所有部門之間都互相知道彼此的存在。只有當兩個部門之間可以直接或間接傳遞資訊時,他們才彼此知道對方的存在。部門之間不會把自己知道哪些部門告訴其他部門。

  上圖中給了一個4個部門的例子,圖中的單向邊表示通路。部門1可以將訊息傳送給所有部門,部門4可以接收所有部門的訊息,所以部門1和部門4知道所有其他部門的存在。部門2和部門3之間沒有任何方式可以傳送訊息,所以部門2和部門3互相不知道彼此的存在。
  現在請問,有多少個部門知道所有N個部門的存在。或者說,有多少個部門所知道的部門數量(包括自己)正好是N。 輸入格式   輸入的第一行包含兩個整數NM,分別表示部門的數量和單向通路的數量。所有部門從1到N標號。
  接下來M行,每行兩個整數ab,表示部門a到部門b有一條單向通路。 輸出格式   輸出一行,包含一個整數,表示答案。 樣例輸入 4 4
1 2
1 3
2 4
3 4 樣例輸出 2 樣例說明   部門1和部門4知道所有其他部門的存在。 評測用例規模與約定   對於30%的評測用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20;
  對於60%的評測用例,1 ≤ N ≤ 100,1 ≤ M ≤ 1000;
  對於100%的評測用例,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000。