题目链接:http://exam.upc.edu.cn/problem.php?id=6348
题目大意:有n头牛,m种喂牛顺序,必须严格按照顺序,然后问你最多能满足几种顺序,必须是最前面n种,不是随便挑。
题目思路:二分,最少0种,最多m种,然后进行拓扑排序,如果成环就说明没办法严格按照顺序,能成环就成立,通过二分找出成立的里面最大的结果
以下是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
#define MAXN 100005
#define ll long long
int n,m,vis[MAXN];
priority_queue<int,vector<int>,greater<int> >q;
vector<int>v[MAXN],g[MAXN];
int pan(int x,int io){
memset(vis,0,sizeof(vis));
rep(i,1,n)v[i].clear();
int st,en,tot=0;
rep(i,1,x){
for(int j=1;j<g[i].size();j++){
st=g[i][j-1],en=g[i][j];
v[st].push_back(en);
vis[en]++;
}
}
while(!q.empty())q.pop();
rep(i,1,n){
if(!vis[i])q.push(i);
}
while(!q.empty()){
int jiang=q.top();
q.pop();
tot++;
for(int i=0;i<v[jiang].size();i++){
int temp2=v[jiang][i];
vis[temp2]--;
if(!vis[temp2])q.push(temp2);
}
if(io){
printf("%d%c",jiang,tot==n?'\n':' ');
}
}
if(tot==n)return true;
else return false;
}
int main(){
while(~scanf("%d%d",&n,&m)){
int num,temp;
rep(i,1,m){
g[i].clear();
scanf("%d",&num);
rep(j,1,num){
scanf("%d",&temp);
g[i].push_back(temp);
}
}
int l=0,r=m,mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(pan(mid,0)){
ans=max(ans,mid);
l=mid+1;
}
else{
r=mid-1;
}
}
int flag=pan(ans,1);
}
return 0;
}