BZOJ 2330 & AcWing 368 (differential constraint determination n + ring) (the third start over)

Topic Link  https://www.acwing.com/problem/content/description/370/

This question, I do three days, the mentality burst ,,, have to say that is a good question 

The vast galaxy of stars, but we only focus on those brightest stars.

We use a positive integer represents the brightness of stars, the larger the value, the brighter stars, star darkest luminance is 1.

Now for the N stars we are concerned, there are M relative relationship between the brightness has determined.

Your job is to determine the sum of the luminance values ​​which are at least N how stars.

Input Format

The first line gives two integers N and M.

After M rows, each row of three integers T, A, B, represents the relationship between the brightness of stars (A, B) couple. Stellar numbers starting with 1.

If T = 1, A and B are equal brightness description.
If T = 2, A is described luminance B is less than the luminance.
If T = 3, A is not described luminance B is less than the luminance.
If T = 4, A is described luminance greater than the luminance of B.
If T = 5, A is described luminance is not larger than the B luminance.

Output Format

Outputting a result integer.

If there is no solution, then it outputs -1.

data range

N≤100000,M≤100000

Consider first the case of no solution, no solution must have occurred in the ring and is a positive ring, if a larger or smaller than established unidirectional edge, and if for equal to or greater than equal edge weight is zero, greater than the edge weight of 1 ( after subtraction Well than 1), if n is a ring, for example: a> bb = c Similarly a> c, but if described in one ring and a a c c a relationship and is not less than a. Thus the case of positive determination is no solution ring. SPFA run it? ohhhh, the amount of data is too big, SPFA time out, I tried to change the queue stack still times out, that this question intentionally card out SPFA, can only open a new path.

Since the right side is not negative, that is to say as long as the right side of a positive value is a positive ring ring may associate strongly connected component, solving the linear time strongly connected components, and then create a new condensing point of view to create a new map process, if found to belong to the two points with a strong component of communication, and the right side is positive between two points, generating a positive ring described -1 direct output to end the program.

If the ring is not positive, then the right side in each strongly connected component are 0, meaning that they have the same brightness, reduction in the new point of view of a single source to give the longest path can seek or topologically sequence DP also possible. I also tried to start a topological order in accordance with DFS, blast stack up

Note: The need to build a super source point, I think somehow, the establishment of super super source from source to start tarjan on all normal, and one by one judge dfn [] is 0 then tarjan to burst stack, make sense of it, or I was too weak, do not understand it  . There is, the result will exceed int range, thus requiring __int64

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
const int N = 100100;
int head[N], nex[N * 4], to[N * 4], ed[N * 4], cnt, head2[N];
int low[N], dfn[N], ind, top, st[N], scc[N], num;
bool vis[N];
vector<int > vec;
int n, m;
bool in[N];
int dist[N];
class Tarjan{
private:
	void add(int* h, int a, int b, int c){
		++cnt;
		to[cnt] = b;
		ed[cnt] = c;
		nex[cnt] = h[a];
		h[a] = cnt;
	}
public:
	Tarjan(){
		mem(head, -1);
		mem(nex, -1);
		mem(head2, -1);
		mem(low, 0);
		mem(dfn, 0);
		mem(scc, -1);
		ind = 0;
		top = 0;
		num = 0;
		vec.clear();
		mem(in, 0);
		mem(dist, 0);
	}
	void init(){
		Tarjan();
	}
	void _add(int* h, int t, int a, int b){
		if (t == 1){
			add(h, a, b, 0);
			add(h, b, a, 0);
		}
		else if (t == 2)add(h, a, b, 1);
		else if (t == 3)add(h, b, a, 0);
		else if (t == 4)add(h, b, a, 1);
		else add(h, a, b, 0);
	}
	void tarjan(int x){
		low[x] = dfn[x] = ++num;
		st[++top] = x;
		vis[x] = 1;
		for (int i = head[x]; i != -1; i = nex[i]){
			int y = to[i];
			if (dfn[y] == 0){
				tarjan(y);
				low[x] = min(low[x], low[y]);
			}
			else if (vis[y])low[x] = min(low[x], dfn[y]);
		}
		if (low[x] == dfn[x]){
			++ind;
			int number = 0;
			for (;;){
				int t = st[top--];
				vis[t] = 0;
				scc[t] = ind;
				number++;
				if (t == x)break;
			}
			vec.push_back(number);
		}
	}
	bool rebuild(){
		for (int i = 0; i <= n; i++){
			for (int j = head[i]; j != -1; j = nex[j]){
				int y = to[j];
				int c = ed[j];
				if (scc[y] == scc[i]){
					if (c > 0)return false;
				}
				else {
					add(head2, scc[i], scc[y], c);
					in[scc[y]] = 1;
				}
			}
		}
		return true;
	}
};
Tarjan tar;
int main()
{
	tar.init();
	scanf("%d %d", &n, &m);
	int t, a, b;
	for (int i = 1; i <= m; i++){
		scanf("%d %d %d", &t, &a, &b);
		tar._add(head, t, a, b);
	}
	for (int i = 1; i <= n; i++)tar._add(head, 2, 0, i);
	tar.tarjan(0);
	bool f = tar.rebuild();
	if (!f){
		printf("-1\n");
	}
	else{
		for (int i = ind; i >= 1; i--){// 拓扑序DP
			for (int j = head2[i]; j != -1; j = nex[j]){
				int y = to[j];
				int c = ed[j];
				if (dist[y] < dist[i] + c){// 求最长路
					dist[y] = dist[i] + c;
				}
			}
		}
		long long ans = 0;
		for (int i = 1; i <= ind; i++){
			ans += dist[i] * vec[i - 1];
		}
		printf("%lld\n", ans);
	}
	return 0;
}

 

Above every mistake I have committed more than once, QAQ 

Published 204 original articles · won praise 13 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_43701790/article/details/104962694