• 拓扑排序——CodeForces-645D


    题目链接

    题目含义

    有一个机器人比赛,只要a能打败b,b能打败c,a就一定能打败c

    然后给出一堆比赛的结果,如果不能得到唯一的所有的机器人战力排名,就输出-1

    如果可以的话,最少能用前几场比赛结果能得到,输出这个最少的比赛次数

    题目分析

    使用拓扑排序,如果出队数不等于机器人数或者某一时刻队列有两个及以上入度为零的点时都输出-1

    而如果满足的话,要找到最少的比赛次数

    如果加一条边用一次拓扑排序的话,明显会超时

    这里提供两种方法

    (1)你有发现拓扑排序每两个点的关系都有在题中给出吗

    比如说4-2-1-3的顺序,一定会给出4打败2,2打败1,1打败3

    而我们要做的就是在拓扑排序中记录每一场必要的比赛结果

    然后在输入里找,当必要的比赛全部出现后,就得到最少的比赛次数了

    (2)可以用二分答案,在输入次数里寻找最少的同时也能满足拓扑排序的次数

    题目代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+7;
    int in[maxn],sum,n,m,a[maxn],b[maxn],head[maxn],tot,copyin[maxn];
    bool flag;
    int fa[maxn],cnt;
    struct edge{
        int to,next;
    }e[maxn];
    bool topusort(){
        queue<int>q;
    //    for(int i=1;i<=n;i++)
    //        copyin[i]=in[i];
        for(int i=1;i<=n;i++)
            if(!in[i])q.push(i);
        int num=0;
        while(!q.empty()){
            if(q.size()>1)return false;
            int u=q.front();q.pop();
            num++;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].to;
                if(--in[v]==0){
                    q.push(v);
                    fa[v]=u;
                    cnt++;
                }
            }
        }return num==n;
    }
    void add(int u,int v){
        e[tot].to=v;
        e[tot].next=head[u];
        head[u]=tot++;
    }
    int main(){
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        int k=0;
    //    flag=false;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a[i],&b[i]);
            add(a[i],b[i]);
            in[b[i]]++;
        }
        if(!topusort())printf("-1
    ");
        else{
            for(int i=1;i<=m;i++){
                if(fa[b[i]]==a[i]){
                    cnt--;
                    if(cnt==0){
                        printf("%d
    ",i);
                        break;
                    }
                }
            }
        }
        return 0;
    }
    第一种做法
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+7;
    int head[maxn],tot,in[maxn];
    struct edge{
        int to,next;
    }e[maxn];
    void add(int u,int v){
        e[tot].to=v;
        e[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,a[maxn],b[maxn];
    bool topusort(int nn){
        memset(head,-1,sizeof(head));
        memset(in,0,sizeof(in));
        tot=0;
        for(int i=1;i<=nn;i++){
            add(a[i],b[i]);
            in[b[i]]++;
        }
        queue<int>q;
        for(int i=1;i<=n;i++)
            if(in[i]==0)q.push(i);
        while(!q.empty()){
            if(q.size()>1)return false;
            int u=q.front();q.pop();
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].to;
                if(--in[v]==0)q.push(v);
            }
        }
    //    cout<<sum<<endl;
        return true;
    //    return sum==n;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&a[i],&b[i]);
        int low=1,high=m;
        int ans=-1;
        while(low<=high){
            int mid=(low+high)>>1;
            if(topusort(mid)){
                ans=mid;
                high=mid-1;
            }
            else low=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    第二种做法

    不知道为什么,我把in数组在拓扑里定义,用它的默认值,结果会错

  • 相关阅读:
    ibatis集成封装之路(to mysql)
    设计模式第一弹—适配器模式
    markdown语法
    outlook vba开发要点
    PHP中json_encode中文编码的问题_学习
    isset、empty、var==null、is_null、var===null详细理解
    对冒泡和二分法,特别是二分法有了更深的理解
    php Socket表单提交学习一下
    php Socket模拟表单上传文件函数_学习
    java第九节 网络编程的基础知识
  • 原文地址:https://www.cnblogs.com/helman/p/11291727.html
Copyright © 2020-2023  润新知