bzoj5280/luogu4376 MilkingOrder (二分答案+拓扑序)
二分答案建图,然后判环,就可以了。
字典序输出的话,只要做拓扑序的时候用优先队列来维护就可以了。
(其实判环也可以用拓扑序...)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 #include<queue> 7 #include<set> 8 #include<ctime> 9 #define LL long long 10 using namespace std; 11 const int maxn=100010,maxm=50050,summ=200020; 12 13 LL rd(){ 14 LL x=0;char c=getchar();int neg=1; 15 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 16 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 17 return x*neg; 18 } 19 20 int N,M; 21 int eg[summ][3],egh[maxn],ect,ine[maxn]; 22 bool flag[maxn],instk[maxn],ans; 23 24 inline void adeg(int a,int b,int m){ 25 eg[++ect][0]=b;eg[ect][1]=egh[a];eg[ect][2]=m;egh[a]=ect; 26 } 27 28 bool dfs(int x,int m){ 29 flag[x]=instk[x]=1;bool re=0; 30 for(int i=egh[x];i!=-1;i=eg[i][1]){ 31 if(eg[i][2]>m) continue; 32 if(!flag[eg[i][0]]) re|=dfs(eg[i][0],m); 33 else if(instk[eg[i][0]]) return 1; 34 }instk[x]=0;return re; 35 } 36 37 int main(){ 38 //freopen("4376.in","r",stdin); 39 int i,j,k; 40 N=rd(),M=rd();memset(egh,-1,sizeof(egh)); 41 for(i=1;i<=M;i++){int last=0; 42 for(j=rd();j;j--){ 43 k=rd();if(last) adeg(last,k,i);last=k; 44 } 45 } 46 int l=1,r=M; 47 while(l<=r){ 48 memset(instk,0,sizeof(instk));memset(flag,0,sizeof(flag)); 49 int m=l+r>>1;bool b=0; 50 for(i=1;i<=N;i++) if(!flag[i]) b|=dfs(i,m); 51 if(b) r=m-1; 52 else{ 53 l=m+1; 54 } 55 }l--; 56 for(i=1;i<=ect;i++){ 57 if(eg[i][2]<=l) ine[eg[i][0]]++; 58 }priority_queue<int,vector<int>,greater<int> > q; 59 for(i=1;i<=N;i++) if(!ine[i]) q.push(i); 60 while(!q.empty()){ 61 int p=q.top();q.pop();printf("%d ",p); 62 for(i=egh[p];i!=-1;i=eg[i][1]){ 63 if(eg[i][2]>l) continue; 64 int b=eg[i][0];ine[b]--; 65 if(!ine[b]) q.push(b); 66 } 67 } 68 return 0; 69 }