POJ-1236 Network of Schools 缩点

题意:就是给我们一个网络 让我们求

1 选择最少的点传信 能够使得这个信息传遍整个网络

2 求加的最少的边 使得 加上这些边后整个图任取一个点信息就可以传到网络中任何一个店


分析: 对于1问 可以用tarjan缩点 把所有的强联通分量缩成一个点 去考虑 然后求一下出度为0的点 就是让信息传遍整个网络的点的数量 如果这里选择根据出度的数量排序用BFS把尽可能多的点标记的做法 会WA 因为用BFS去考虑的话 只考虑了出度没有考虑入度 有些点考虑不到 就是那些入度为0出度比较小的点 网络中只有搞定了这些点才能让一个信息传遍整个网络 因为入度为0的点 无论怎么考虑出度 都不会有边能够沟通到这类点 

对于2问 还是统计出入度和出度为0的点 我们考虑 对于一个网络 只要把他改造成一个强联通图 这个图中的任意亮点就都可达了

也就是解决入度为0和出度为0的点 因为入度为0的点 没人穿的到他 出度为0的点信息给他出不去 所以当我们让这两类点一对一互相联通 剩下的多余的任意连 即可沟通整个网络

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;

class node implements Comparable<node>{
	int id,edge;
	node(){}
	node(int a,int b){this.id = a;this.edge = b;}
	@Override
	public int compareTo(node p) {
		// TODO Auto-generated method stub
		if(p.edge<=this.edge)return 1;
		else return -1;
	}
	
}

public class Main {
	static final int maxn = 110;
	static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
	static ArrayDeque<Integer> que = new ArrayDeque<Integer>();
	static ArrayDeque<Integer> S = new ArrayDeque<Integer>();
	static int head[] = new int[maxn*maxn];
	static int to[] = new int[maxn*maxn];
	static int next[] = new int[maxn*maxn];
	
	static boolean bok[] = new boolean[maxn];
	static boolean isS[] = new boolean[maxn];
	
	static int tag=0,cnt=0,ans1 =0 ,ans2=0,ind;
	
	static int dfn[] = new int[maxn];
	static int low[] = new int[maxn];

	static node nod[] = new node[maxn];
	static int[] id = new int[maxn];
	static int cir;
	static int in[] = new int [maxn];
	static int out1[] = new int[maxn];

	static void dfs(int x) {
		dfn[x] = low[x] = ++ind;
		S.push(x);isS[x] = true;
		for(int i=head[x];i!=-1;i = next[i]) {
			int t=to[i];
			if(dfn[t]==0) {
				dfs(t);
				low[x] = Math.min(low[t], low[x]);
			}
			else if(isS[t])
				low[x] = Math.min(low[x],dfn[t]);
		}
		if(dfn[x]==low[x]){
			ans2++;
			++cir;
			while(true){
				int t;
				if(!S.isEmpty()) {
					t = S.peek();
					S.pop();isS[t] = false;
					id[t] = cir;					
					if(t==x)break;
				}
			}
		}
	}	
	static void addEdge(int x,int t) {	
		to[tag] = t;
		next[tag] = head[x];
		head[x] = tag++;
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(new BufferedInputStream(System.in));
		while(sc.hasNext()) {
			int n = sc.nextInt();
			Arrays.fill(head,-1);
			Arrays.fill(bok, false);
			Arrays.fill(isS, false);
			Arrays.fill(dfn, 0);
			Arrays.fill(low, 0);
			
			Arrays.fill(in,0);
			Arrays.fill(out1, 0);
			
			cir = tag=cnt=ans1=ans2=ind=0;
			
			for(int i=1;i<=n;i++) {
				if(nod[i]==null)nod[i] = new node(i,0);
				else {nod[i].id = i;nod[i].edge=0;}
				while(true) {
					int t = sc.nextInt();
					if(t==0)break;
					addEdge(i,t);		
				}			
			}
			for(int i=1;i<=n;i++) {
				if(dfn[i]==0) {
					S.clear();
					dfs(i);
				}
			}
			
			for(int i=1;i<=n;i++) {
				for(int j = head[i];j!=-1;j=next[j]){
					int t = to[j];
					if(id[t]!=id[i]){
						in[id[t]]++;
						out1[id[i]]++;
					}
				}
			}
			
			int Iy = 0;
			for(int i=1;i<=cir;i++)
				if(in[i]==0) {
					ans1++;
				}else if(out1[i]==0) {
					Iy++;
				}
			
			
			
			out.println(ans1);
			if(cir==1)out.println(0);
			else out.println(Math.max(ans1, Iy));
			out.flush();			
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值