您的位置:首页 > 移动开发

CodeForces 645 D.Robot Rapping Results Report(二分+dfs)

2017-04-28 14:45 435 查看
Description

n个机器人,每个机器人有一个不同的级别,级别介于1~n,高级别的可以打败低级别的,现在给出n个机器人的m场比赛胜负情况,问最少需要前几场比赛就可以确定每个机器人的级别

Input

第一行两个整数n和m表示机器人个数和比赛场数,之后m行每行两个整数u和v表示机器人u打败机器人v

(2<=n<=1e5,1<=m<=min(n*(n-1)/2,1e5))

Output

如果这m场比赛可以确定每个机器人的级别则输出最少需要前几场比赛就可以确定,否则输出-1

Sample Input

4 5

2 1

1 3

2 3

4 2

4 3

Sample Output

4

Solution

把每个机器人看作一个点,根据比赛结果建图,赢的向输的建边,那么能确定每个机器人的级别的情况就是该图是一个深度为n的树,所以二分答案,对每个二分值建图dfs判断树的深度是否为n即可

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 111111
int n,m,edge[maxn][2],in[maxn],pre,num[maxn];
vector<int>g[maxn];
int dfs(int u)
{
if(num[u])return num[u];
num[u]=1;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
dfs(v);
num[u]=max(num[u],num[v]+1);
}
return num[u];
}
bool check(int x)
{
if(x<pre)
{
for(int i=x+1;i<=pre;i++)
g[edge[i][0]].pop_back(),in[edge[i][1]]--;
}
else
{
for(int i=pre+1;i<=x;i++)
g[edge[i][0]].push_back(edge[i][1]),in[edge[i][1]]++;
}
for(int i=1;i<=n;i++)
if(in[i]==0)
{
memset(num,0,sizeof(num));
if(dfs(i)==n)return 1;
return 0;
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=m;i++)scanf("%d%d",&edge[i][0],&edge[i][1]);
for(int i=1;i<=n;i++)g[i].clear();
memset(in,0,sizeof(in));
for(int i=1;i<=m;i++)
g[edge[i][0]].push_back(edge[i][1]),in[edge[i][1]]++;
pre=m;
if(!check(m))printf("-1\n");
else
{
int l=1,r=m-1,mid,ans=m;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
pre=mid;
}
printf("%d\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐