題解 P3275 【[SCOI2011]糖果】

清深夏令營機考壓軸題,對差分約束的認識還是不夠深刻,算法寫出來了圖沒建對,/(ㄒoㄒ)/~~

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
#define P pair<int,int>
#define MAX 100005

int N, K, x, a, b, vis[MAX], cnt[MAX], dist[MAX];
struct edge {
	int v, c;
	edge(int a = 0, int b = 0) { v = a, c = b; }
};
vector<edge>G[MAX];

void addEdge(int x, int a, int b) {
	if (x == 1)G[a].push_back(edge(b, 0)), G[b].push_back(edge(a, 0));
	else if (x == 2)G[a].push_back(edge(b, 1));
	else if (x == 3)G[b].push_back(edge(a, 0));
	else if (x == 4)G[b].push_back(edge(a, 1));
	else G[a].push_back(edge(b, 0));
}

bool spfa(int s) {
	memset(vis, 0, sizeof(vis));
	memset(cnt, 0, sizeof(cnt));
	fill(dist, dist + MAX, 0);
	queue<int> q; q.push(s); vis[s] = 1; dist[s] = 0;

	while (!q.empty()) {
		int u = q.front(); q.pop(); cnt[u]++; vis[u] = 0;
		if (cnt[u] == N)return false;
		for (int i = 0; i < G[u].size(); i++) {
			edge e = G[u][i];
			if (dist[u] + e.c > dist[e.v]) {
				dist[e.v] = dist[u] + e.c;
				if (!vis[e.v]) {
					vis[e.v] = 1;
					q.push(e.v);
				}
			}
		}
	}
	return true;
}

int main() {
	while (scanf("%d %d", &N, &K) != EOF) {
		for (int i = 0; i <= N; i++) {
			G[i].clear();
			if (i != 0)G[0].push_back(edge(i, 1));//超級源點
		}
		int sign = 1;
		for (int i = 0; i < K; i++) {
			scanf("%d %d %d", &x, &a, &b);
			if (x == 2 || x == 4) {
				if (a == b) { sign = 0; }
			}
			addEdge(x, a, b);
		}
		if (!sign) { cout << -1 << endl; continue; }

		if (!spfa(0))cout << -1 << endl;
		else {
			ll mi = inf, res = 0;
			for (int i = 1; i <= N; i++) {
				if (dist[i] < mi)mi = dist[i];
				res += dist[i];
			}
			if (mi < 0)
				res += (-mi + 1)*N;
			cout << res << endl;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章