题意是给你一个长度小于10的数列,再给你任意子段和的符号。让你输出这一个数列,本题难度在于如何构图。
首先要说明的是由于给你的矩阵是任意子段和的符号,所以我们求解的时候可以先求解前缀和,然后也能很方便的在输出时将其转换成我们要得数列。
再说一下如何构图,首先我们定义边的含义:i->j的边表示s[i]>s[j]。一旦想到这个算法就清晰了,我们只要进行拓扑排序,然后再排序构成中对于每一个s[i]进行赋值就OK了。
代码如下:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #define INF 0x7fffffff 13 #define ll long long 14 #define eps 1e-6 15 #define LEN 13 16 17 using namespace std; 18 19 int Map[LEN][LEN], Indegree[LEN], s[LEN], n, vis[LEN]; 20 21 void topsort(){ 22 queue<int> q; 23 memset(vis, 0, sizeof vis); 24 for(int i=0; i<=n; i++){ 25 if(Indegree[i]==0){ 26 q.push(i); 27 s[i] = 10; 28 vis[i] = 1; 29 } 30 } 31 while(!q.empty()){ 32 int vex = q.front(); q.pop(); 33 for(int i=0; i<=n; i++){ 34 if(Map[vex][i]){ 35 Indegree[i]--; 36 if(Indegree[i]==0 && vis[i]==0){ 37 vis[i] = 1; 38 q.push(i); 39 s[i] = s[vex]-1; 40 } 41 } 42 } 43 } 44 } 45 46 int main() 47 { 48 // freopen("in.txt", "r", stdin); 49 50 int T; 51 scanf("%d", &T); 52 while(T--){ 53 scanf("%d", &n); 54 memset(Map, 0, sizeof Map); 55 memset(Indegree, 0, sizeof Indegree); 56 memset(s, 0, sizeof s); 57 for(int i=1; i<=n; i++){ 58 for(int j=i; j<=n; j++){ 59 char temp; 60 cin >> temp; 61 if(temp=='+'){ 62 Map[j][i-1] = 1; 63 Indegree[i-1]++; 64 }else if(temp=='-'){ 65 Map[i-1][j] = 1; 66 Indegree[j]++; 67 } 68 } 69 } 70 topsort(); 71 for(int i=1; i<=n; i++){ 72 printf("%d", s[i]-s[i-1]); 73 if(i!=n) printf(" "); 74 else printf(" "); 75 } 76 } 77 return 0; 78 }