uva 1423 LA 4255

这道题目思维+基础,好题目

拓扑排序

以后看到sij就要想到连续和转化为前缀和之差的思想,通过表格得到两两前缀和的大小关系,然后通过拓扑排序得到前缀和的大小序列,确定每个前缀和的大小,最后得到结果

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn=11;
int e[maxn][maxn],b[maxn],in[maxn],sol[maxn];
int n,loc;
void topo()//基于栈的topo排序
{
	int i;
	int top=-1;//栈顶指针,一个没有额外使用内存,抽象的栈,巧妙的技巧
	for(i=0;i<=n;i++)
	{
		if(!in[i])
		{
			in[i]=top;//判断完此节点知其入度为0,加入栈中,那么in[i]以后就没有什么作用了
			          //可用来存储入了栈的这一节点在栈中下一个元素的标号
			top=i;
		}
	}
	for(i=0;i<=n;i++)
	{
		//if(top==-1) break;
		int t=top;
		if(!t) loc=i;
		sol[i]=t;
		top=in[top];
		for(int j=0;j<=n;j++)
		{
			if(e[t][j])
			{
				in[j]--;
				if(!in[j])
				{
					in[j]=top;
					top=j;
				}
			}
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	getchar();
	while(t--)
	{
		int i,j;
		scanf("%d",&n);
		char c;
		getchar();
		memset(e,0,sizeof(e));
		memset(in,0,sizeof(in));
		for(i=1;i<=n;i++)
		{
			for(j=i;j<=n;j++)
			{
				scanf("%c",&c);
				if(c=='+') { e[j][i-1]=1; in[i-1]++; }
				if(c=='-') {e[i-1][j]=1; in[j]++; }
			}
		}
		getchar();
		topo();
		b[0]=0;
		for(i=loc-1;i>=0;i--)
		{
			int t1=sol[i],t2=sol[i+1];
			if(!e[t1][t2]) b[t1]=b[t2];
			else b[t1]=b[t2]+1;
		}
		for(i=loc+1;i<=n;i++)
		{
			int t1=sol[i],t2=sol[i-1];
			if(!e[t2][t1]) b[t1]=b[t2];
			else b[t1]=b[t2]-1;
		}
		for(i=1;i<n;i++) printf("%d ",b[i]-b[i-1]);
		printf("%d\n",b[n]-b[n-1]);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/lj030/p/3002337.html