zoukankan      html  css  js  c++  java
  • 洛谷 P2296 [NOIP2014 提高组] 寻找道路(反图bfs)

    传送门


    解题思路

    首先明白题意:
    能经过的点必须满足其所有连向的节点都能走到终点。
    于是我们就可以建个反图,跑一遍dfs,求出有多少满足条件的点,最后bfs跑一遍即可。
    如何判断?
    用一个num数组表示节点i在原图的出度,即在反图的出度。
    每当有一个点指向节点i时,num[i]--。
    最后若num[i]为0则满足条件。
    注意因为有环,所以要记录vis数组,保证每个节点只会使其连向的节点最多减少一。

    AC代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxm=200005;
    int n,m,s,t,vis[10005],p[10005],cnt,dis[10005],num[10005];
    queue<int> q;
    struct node{
    	int v,next;
    }e[maxm*2];
    void insert(int u,int v){
    	cnt++;
    	e[cnt].v=v;
    	e[cnt].next=p[u];
    	p[u]=cnt;
    }
    void dfs(int u){
    	vis[u]=1;
    	for(int i=p[u];i!=-1;i=e[i].next){
    		int v=e[i].v;
    		num[v]--;
    		if(vis[v]) continue;
    		dfs(v);
    	}
    }
    int main(){
    	memset(p,-1,sizeof(p));
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		int u,v;
    		cin>>u>>v;
    		insert(v,u);
    		num[u]++;
    	}
    	cin>>s>>t;
    	dfs(t);
    	memset(vis,0,sizeof(vis));
    	q.push(t);
    	vis[t]=1;
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=p[u];i!=-1;i=e[i].next){
    			int v=e[i].v;
    			if(num[v]!=0||vis[v]) continue;
    			vis[v]=1;
    			dis[v]=dis[u]+1;
    			q.push(v); 
    			if(v==s){
    				cout<<dis[s];
    				return 0;
    			}
    		}
    	}
    	cout<<-1;
        return 0;
    }
    

    //NOIP2014提高组Day2 t2

  • 相关阅读:
    kubernetes dashboard 二次开发
    grafana二次开发
    Harbor 定制页面 和 二次开发指南
    spring boot 知识点1
    spring boot2.1读取 apollo 配置中心3
    apollo 部门管理
    spring boot2.1读取 apollo 配置中心2
    a 产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复。
    Net上机考试
    Net(ASP.NET)程序设计
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15068508.html
Copyright © 2011-2022 走看看