zoj2997(拓扑排序)

来源:互联网 发布:s.click是淘宝网的吗 编辑:程序博客网 时间:2024/06/10 04:02

Black and White

Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge

Write a program which reads three positive integers n, p, q. Decide whether or not there exists a sequence of n integers such that the sum of any p consecutive elements is positive and the sum of any q consecutive ones is negative. If the answer is YES, your program has to produce such a sequence.

Input

Each line of the input file will be 3 single positive numbers n, p, q You may assume that 0 < n, p , q < 5000.

Output

The output consists of NO or YES followed by a sequence of n integers written on display.

Sample Input

4 2 36 5 3

Sample Output

NOYES-3 5 -3 -3 5 -3

题意:有一个长为n的数组,每连续p项之和为正数,每连续q项之和为负数。构造出这个数组,如果构造不出,则输出NO。

思路:经典的拓扑排序,构造一个长度为 N 的序列,使得序列所有连续 P 个元素之和为正,且所有连续 Q 个元素之和为负。将问题转化,构造这个序列的累加序列,相当于构造一个长度为 N + 1 的序列 S[0..N],满足 S[i+P] - S[i] > 0 且 S[i+Q] - S[i] < 0。这样的话,可以构造 N+1 顶点的图,将所有 S[i] > S[j] 的关系创建有向边 (i, j) 。那么,将这个图拓扑排序,然后如果有环,则不可构造,否则,其深搜弹出序号本身即可作为 S[i] 的值(因为只要满足大小顺序即可)。


#include<iostream>#include<stdio.h>#include<string.h>#include<stack>using namespace std;int n,p,q;bool S[5005][5005];int ind[5005];int res[5005];stack<int>sta;int main(){while(~scanf("%d%d%d",&n,&p,&q)){memset(S,0,sizeof(S));memset(ind,0,sizeof(ind));memset(res,0,sizeof(res));while(!sta.empty())sta.pop();for(int i=0;i<=n-p;i++){S[i][i+p]=1;   //小的->大的 ind[i+p]++;}for(int i=0;i<=n-q;i++){S[i+q][i]=1;ind[i]++;}int cnt=0;for(int i=0;i<=n;i++){if(!ind[i]){res[i]=cnt++;sta.push(i);}}while(!sta.empty()){int k=sta.top();sta.pop();for(int i=0;i<=n;i++){if(S[k][i]){ind[i]--;if(!ind[i]){res[i]=cnt++;sta.push(i);}}}}if(cnt<n+1){printf("NO\n");continue;}else{printf("YES\n");for(int i=1;i<n;i++){printf("%d ",res[i]-res[i-1]);}printf("%d\n",res[n]-res[n-1]);}}}