题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2256
思路:
1.对于前缀和sum[i]、sum[j]:若i到j的和为负数,则连边(i-1)--->j(代表sum[j]-sum[i-1]<0,即sum[j]<sum[i-1]);若和为正数,则连边j--->(i-1)(代表sum[j]-sum[i-1]>0,即sum[j]>sum[i-1])。
2.进行拓扑排序:从10开始赋值sum[i],依次递减(节点数只有10,最小减到1),每次对于入度为0的点将其赋同一值(保证等于0的情况)。
3.a[i]=sum[i]-sum[i-1],最大值为10,最小值为1,保证在-10到10范围内。
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug
using namespace std;
const int maxn=100;
int n;
int d[maxn];
queue<int> q;
int sum[maxn];
vector<int> g[maxn];
void topsort()
{
while(!q.empty()) q.pop();
int cnt=10;
for(int i=0; i<=n; i++)
{
if(d[i]==0)
{
q.push(i);
sum[i]=cnt;
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
cnt--;
for(int i=0; i<g[now].size(); i++)
{
int nt=g[now][i];
if(--d[nt]==0)
{
sum[nt]=cnt;
q.push(nt);
}
}
}
}
void init()
{
memset(d,0,sizeof(d));
for(int i=0; i<=n; i++) g[i].clear();
}
int main()
{
#ifdef debu
freopen("in.txt","r",stdin);
#endif // debug
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
getchar();
for(int i=1; i<=n; i++)
{
for(int j=i; j<=n; j++)
{
char ch;
scanf("%c",&ch);
if(ch=='-')
{
g[i-1].push_back(j);
d[j]++;
}
else if(ch=='+')
{
g[j].push_back(i-1);
d[i-1]++;
}
}
}
topsort();
for(int i=1; i<=n; i++)
{
if(i!=1) printf(" ");
printf("%d",sum[i]-sum[i-1]);
}
printf("\n");
}
return 0;
}