题目转不过来: 点击打开链接
这个题真是万万没想到是拓扑排序啊啊啊,以为和之前有一个变换质数的题一样是深搜==挑了半天没看出来哪里错了⊙﹏⊙b汗 先说拓扑排序是什么来着,这也是扔了几乎半年的知识点==,通过找连着的边,让点的入度减少,入度为0的点入队列,从而形成一条可行路径== 这题是白书训练指南310页的例题,“连续和转化为前缀之和”这个性质我想到了,但是没想到正负号就可以确定前后两个前缀和从而在拓扑排序中建边==从大往小建边,最开始假设都是0,逐步调整s[v]=min(s[v],s[u]-1);应该是尽量让差值最小?
这个题真是万万没想到是拓扑排序啊啊啊,以为和之前有一个变换质数的题一样是深搜==挑了半天没看出来哪里错了⊙﹏⊙b汗 先说拓扑排序是什么来着,这也是扔了几乎半年的知识点==,通过找连着的边,让点的入度减少,入度为0的点入队列,从而形成一条可行路径== 这题是白书训练指南310页的例题,“连续和转化为前缀之和”这个性质我想到了,但是没想到正负号就可以确定前后两个前缀和从而在拓扑排序中建边==从大往小建边,最开始假设都是0,逐步调整s[v]=min(s[v],s[u]-1);应该是尽量让差值最小?
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=300;
int head[maxn],ip,indegree[maxn];
int n,m,seq[maxn];
int s[23];
struct note
{
int v,next;
} edge[maxn*maxn];
void init()
{
memset(head,-1,sizeof(head));
ip=0;
memset(s,0,sizeof(s));
memset(indegree,0,sizeof(indegree));
}
void addedge(int u,int v)
{
edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}
void topo()///拓扑,可做模板
{
queue<int>q;
int indeg[maxn];
for(int i=0; i<=n; i++)
{
indeg[i]=indegree[i];
if(indeg[i]==0)
q.push(i);
}
int k=0;
bool res=false;
while(!q.empty())
{
// if(q.size()!=1)res=true;
int u=q.front();
q.pop();
// seq[k++]=u;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v ;
s[v]=min(s[v],s[u]-1);
indeg[v]--;
if(indeg[v]==0)
{
q.push(v);
}
}
}
// if(k<n)return -1;///存在有向环,总之不能进行拓扑排序
// if(res)return 0;///可以进行拓扑排序,并且只有唯一一种方式,seq数组即是排序完好的序列
// return 1;///可以进行拓扑排序,有多种情况,seq数组是其中一种序列
}
int main()
{
// freopen("cin.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
char flag[200];
scanf("%s",flag);
for(int i=1,k=0;i<=n;i++)
for(int j=i;j<=n;j++,k++)
{
if(flag[k] == '-')
{
addedge(i-1,j);
indegree[j]++;
}
else if(flag[k] == '+')
{
addedge(j,i-1);
indegree[i-1]++;
}
}
topo();
{
int ans[20];
for(int i=1;i<=n;i++)ans[i]=s[i]-s[i-1];
for(int i=1;i<n;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
}
return 0;
}