我是靠谱客的博主 魁梧大门,最近开发中收集的这篇文章主要介绍拓扑排序——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("-1n");
else{
for(int i=1;i<=m;i++){
if(fa[b[i]]==a[i]){
cnt--;
if(cnt==0){
printf("%dn",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("%dn",ans);
return 0;
}
第二种做法

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

转载于:https://www.cnblogs.com/helman/p/11291727.html

最后

以上就是魁梧大门为你收集整理的拓扑排序——CodeForces-645D的全部内容,希望文章能够帮你解决拓扑排序——CodeForces-645D所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部