zoukankan      html  css  js  c++  java
  • HDU3342有向图判圈DFS&&拓扑排序法

    HDU3342 Legal or Not

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3342

    题目意思:一群大牛互相问问题,大牛有不会的,会被更厉害的大牛解答,更厉害的大牛是会的东西比大牛多,但是有的时候更厉害的大牛会装弱,出来问问题,这样就被大牛解答了。这样就形成了一个圈。题目的意思就是让你在一个有向图里面判断是否存在环。我们可以通过dfs和拓扑排序两种方法。

    DFS的代码:

    //Author: xiaowuga
    #include <bits/stdc++.h>
    #define maxx INT_MAX
    #define minn INT_MIN
    #define inf 0x3f3f3f3f
    const long long N=100000+10; 
    using namespace std;
    typedef long long L;
    vector<int>q;
    vector<int>p[N];
    int in[N];
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        int n,m;
        while(cin>>n>>m){
            q.clear();
            memset(in,0,sizeof(in));
            for(int i=1;i<=n;i++) p[i].clear();
            q.clear();
            int reward[N];
            for(int i=1;i<=n;i++) reward[i]=888;
            for(int i=0;i<m;i++){
                int a,b;
                cin>>a>>b;
                p[b].push_back(a);
                in[a]++;
            }
            int ct=0,ans=0;
            for(int i=1;i<=n;i++) if(!in[i]) {q.push_back(i);ans+=reward[i];}
            while(q.size()!=0){
                int t=q.back();q.pop_back();
                ct++;
                for(int i=0;i<p[t].size();i++){
                    int x=p[t][i];
                    if(--in[x]==0){
                        q.push_back(x);
                        reward[x]=max(reward[x],reward[t]+1);
                        ans+=reward[x];
                    }
                    else{
                        reward[x]=max(reward[x],reward[t]+1);
                    }
                }
            }
            if(ct!=n){
                cout<<-1<<endl;
            }
            else cout<<ans<<endl;
        }
        return 0;
    }

    dfs的思路,就是一路遍历做标记,然后如果遍历到已经遍历过的就说明存在环,但是一找到环就可以break,跳出,结束dfs,可以剪枝,不然会超时,因为一个点可能遍历很多遍,所以dfs是比较慢的。

    拓扑排序的做法

    为什么可以判圈我在我的另外一篇博文里面已经说清楚了:http://www.cnblogs.com/xiaowuga/p/7218382.html

    还是把一个环缩成一个点思想,环上的大小关系的等价的,从而无法遍历所有的点,通过遍历点的数量来判断是否形成环。

    代码:

    //Author: xiaowuga
    #include <bits/stdc++.h>
    #define maxx INT_MAX
    #define minn INT_MIN
    #define inf 0x3f3f3f3f
    const long long N=100000+10; 
    using namespace std;
    typedef long long L;
    vector<int>q;
    vector<int>p[N];
    int in[N];
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        int n,m;
        while(cin>>n>>m&&n&&m){
            q.clear();
            memset(in,0,sizeof(in));
            for(int i=0;i<n;i++) p[i].clear();
            q.clear();
            for(int i=0;i<m;i++){
                int a,b;
                cin>>a>>b;
                p[b].push_back(a);
                in[a]++;
            }
            int ct=0;
            for(int i=0;i<n;i++) if(!in[i]) {q.push_back(i);}
            while(q.size()!=0){
                int t=q.back();q.pop_back();
                ct++;
                for(int i=0;i<p[t].size();i++){
                    int x=p[t][i];
                    if(--in[x]==0){
                        q.push_back(x);
                    }
                }
            }
            if(ct!=n){
                cout<<"NO"<<endl;
            }
            else cout<<"YES"<<endl;
        }
        return 0;
    }
  • 相关阅读:
    react-redux简单使用
    jQuery——Js与jQuery的相互转换
    移除HTML5 input在type="number"时的上下小箭头
    echarts 5.0 地图
    Vue echarts 设置初始化默认高亮
    echarts 渐变色
    隐藏滚动条css
    echarts 柱状图--圆角
    echarts 气泡图--option
    Vue 圆柱体组件
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7219715.html
Copyright © 2011-2022 走看看