• 洛谷P2746校园网


    传送门啦

    下面来看任务B。我们发现,图中只要存在入度为0的点和出度为0的点就永远不可能满足要求:“ 不论我们给哪个学校发送新软件,它都会到达其余所有的学校 ”。我们还发现,只要在入度为0的点和出度为0 的点之间连一条边,就可以同时消灭两个“不合法”的点。如果不能做到刚好两两配对(不妨假设入度为0的点多),就给每个多出来的入度为0的点随便找一个出度为0的点配对(也就是说一个点可以同时配多个点)。因此,入度为0的点数与出度为0的点数的较大值即为任务B的答案。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 5e6 + 6;
    int read(){
    	char ch = getchar();
    	int f = 1 , x = 0;
    	while(ch > '9' || ch < '0'){
    		if(ch == '-')  f = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9'){
    		x = x * 10 + ch - '0';
    		ch = getchar();
    	}
    	return x * f;
    }
    
    int n,m,s;
    int head[maxn],tot;
    int dfn[maxn],low[maxn],ind;
    int stack[maxn],top,num[maxn],belong[maxn],cnt;
    bool ins[maxn];
    int in[maxn],chu[maxn],ans1,ans2;
    struct Edge{
    	int from,to,next;
    }edge[maxm];
    
    void add(int u , int v){
    	edge[++tot].from = u;
    	edge[tot].to = v;
    	edge[tot].next = head[u];
    	head[u] = tot;
    } 
    
    void tarjan(int x){
    	low[x] = dfn[x] = ++ind;
    	ins[x] = true;
    	stack[++top] = x;
    	for(int i=head[x];i;i=edge[i].next){
    		int v = edge[i].to;
    		if(ins[v])  low[x] = min(low[x] , dfn[v]);
    		if(!dfn[v]) {
    			tarjan(v);
    			low[x] = min(low[x] , low[v]);
    		} 
    	}
    	int k = 0;
    	if(dfn[x] == low[x]){
    		cnt++;
    		do{
    			k = stack[top];
    			num[cnt]++;
    			top--;
    			ins[k] = false;
    			belong[k] = cnt;
    		}  while(k != x);
    	}
    }
    
    int main(){
    	n = read();
    	for(int i=1;i<=n;i++){
    		while((s = read()) != 0){
    			m++;
    			add(i , s);
    		}
    	}
    	//printf("%d
    ",m);
    	for(int i=1;i<=n;i++)
    	  if(!dfn[i])  tarjan(i);
    	for(int i=1;i<=m;i++)
    	  if(belong[edge[i].from] != belong[edge[i].to]){
    	  	  in[belong[edge[i].to]]++;
    	  	  chu[belong[edge[i].from]]++;
    	  }
    	if(cnt == 1){
    		printf("1
    0
    ");
    		return 0;
    	}  
    	else{
    		for(int i=1;i<=cnt;i++){
    			if(in[i] == 0)  ans1++;
    			if(chu[i] == 0)  ans2++;
    		}
    		printf("%d
    %d",ans1,max(ans1 , ans2));
    		return 0;
    	}
    	
    }
    
    /*
    10
    2 0
    3 0
    4 0
    5 0
    6 0
    7 0
    8 0
    9 0
    10 0
    1 0
    */ 
    
    顺风不浪,逆风不怂。
  • 相关阅读:
    利用Lucene将被索引文件目录中的所有文件建立索引
    Carrot2 in action 初步印象
    Lucene建立索引搜索入门实例
    Lucene索引文件组成
    模拟浏览器登陆的基本思路与做法
    HttpWatch使用教程
    httpclient 怎么带上登录成功后返回的cookie值访问下一页面
    Google开源库-Volley的使用
    Android Material Design 学习笔记
    2015年山东省齐鲁软件大赛总结
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9883268.html
Copyright © 2020-2023  润新知