没怎么好好的学过拓扑排序,恰好有一道训练题是拓扑排序,记录一下。
题意:给你ai 到aj这些数(1<=i<=j<=n)总和的关系,让你求a1到an
题解:转换一下思维,题意给出的就是sum[j] - sum[i-1]的关系,于是我们就可以得出sum[i]、sum[j]的许多大小关系,那我们求a[i]就是求sum[i] - sum[i-1],所以我们根据这些sum的关系可以得到一个拓扑序,最小值赋为0,每次加一,就可以满足题目中各种条件了,十分巧妙。
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <sstream>
#define mod 1000000007
#define INF 0x3f3f3f3f
#define fuck() (cout << "----------------------------------------" << endl)
using namespace std;
const int maxn = 2000 + 10;
int n;
int sum[maxn];
int du[maxn];
vector<int> vec[maxn];
char x[maxn];
void topu()
{
int temp = 0;
queue < int > q;
for(int i=0; i<=n; i++)
if(du[i] == 0)
q.push(i);
while(!q.empty())
{
int k = q.size();
for(int i=0; i<k; i++)
{
int u = q.front();
q.pop();
sum[u] = temp;
for(int j=0; j<vec[u].size(); j++)
{
int v = vec[u][j];
du[v]--;
if(du[v] == 0)
q.push(v);
}
}
temp++;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(int i=0; i<maxn; i++) vec[i].clear();
scanf("%s",x);
int p = 0;
for(int i=1; i<=n; i++)
{
for(int j=i; j<=n; j++)
{
if(x[p] == '+')
{
du[j]++;
vec[i-1].push_back(j);
}
else if(x[p] == '-')
{
du[i-1]++;
vec[j].push_back(i-1);
}
p++;
}
}
topu();
for(int i=1; i<=n; i++)
{
if(i == 1) printf("%d",sum[i] - sum[i-1]);
else printf(" %d",sum[i] - sum[i-1]);
}
printf("\n");
}
}