UVa 1423

题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=4169&mosmsg=Submission+received+with+ID+26578906

将区间和拆成前缀和的差,条件转化为前缀和两两之间的大小关系,以大小关系连有向边,进行拓扑排序,按拓扑序给前缀和赋值

需要注意的是,如果两个前缀和是相等关系,需要使用并查集合并节点,不能简单地另其中一个等于另一个,因为可能有很多个前缀和节点都相等

最后注意输出格式问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 310;

int T, n; 
int a[maxn], b[maxn];
int deg[maxn];

char ch[maxn], c[maxn][maxn];

int h[maxn], cnt = 0;
struct E{
	int to, next;
}e[maxn << 1];
void add(int u, int v){
	e[++cnt].to = v;
	e[cnt].next = h[u];
	h[u] = cnt;
}

int par[maxn];
int find(int u){
	return par[u] == u ? u : par[u] = find(par[u]);
}

vector<int> path; 
int in[maxn];

void topo(){
	queue<int> q;
	
	for(int i = 0 ; i <= n ; ++i){
		if(!deg[i] && in[i]) {
			q.push(i);
			path.push_back(i);
		}
	}
	
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int i = h[u] ; i != -1 ; i = e[i].next){
			int v = e[i].to;
			--deg[v];
			if(!deg[v]){
				q.push(v);
				path.push_back(v);
			}
		}
	}
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	scanf("%d", &T);
	while(T--){
		path.clear();
		memset(in, 0, sizeof(in));
		memset(h, -1, sizeof(h)); cnt = 0;
		memset(deg, 0, sizeof(deg));
		
		scanf("%d", &n);
		scanf("%s", ch + 1);
		for(int i = 0 ; i <= n ; ++i) par[i] = i;

		int pos = 1;
		for(int i = 1 ; i <= n ; ++i){
			for(int j = i ; j <= n ; ++j){
				c[i][j] = ch[pos];
				if(ch[pos++] == '0') par[j] = i - 1;
			}
		}	
		
		for(int i = 1 ; i <= n ; ++i){
			for(int j = i ; j <= n ; ++j){
				if(c[i][j] == '+'){
					add(find(i - 1), find(j));
					++deg[find(j)];
					in[find(i - 1)] = 1;
					in[find(j)] = 1;
				}
				if(c[i][j] == '-'){
					add(find(j), find(i - 1));
					++deg[find(i - 1)];
					in[find(i - 1)] = 1;
					in[find(j)] = 1;
				}
			}
		}
		
		topo();
		
		int val = 0;
		for(int i = 0 ; i < path.size() ; ++i){
			b[path[i]] = val++; 
		}
			
		for(int i = 1 ; i <= n ; ++i){
			b[i] = b[find(i)];
			if(i > 1) printf(" ");
			printf("%d", b[i] - b[i - 1], (i == n) ? '
' : ' ');
		} printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/15022331.html