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 list[];
	static List 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();
			list2[i] = new ArrayList();
		}
		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 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。



你可能感兴趣的:(JAVA,数据结构,算法学习,搜索-bfs,搜索-dfs,OJ,Test)