zoj 2770 Burn the Linked Camp 差分约束

       设x[i] 为第i个营的人数,s[i] = x[1] + x[2] + … + x[i], s[0] = 0

       则对于题目

       Ci 有: 0 <= s[i] – s[i-1] <= Ci

       i, j, k有: s[j] – s[i-1] >= k

       还有: s[i] >= 0 (1 <= i <= n) , 即 s[i] – s[0] >= 0

       这题求最小值,以0为源点求最长路

 

#include<iostream>

#include <queue>

#include <cstdio>

#include <cstring>

using namespace std;



const int MAX = 20000;

const int INF = 1000000000;

const int N = 10000;



struct Node

{

	int v;

	int cost;

	int next;

};



Node node[MAX];

int adj[N];

int d[N];

bool in_q[N];

int cnt[N];

int size;

int n, m;



void add_edge(int u, int v, int cost)

{

	node[size].v = v;

	node[size].cost = cost;

	node[size].next = adj[u];

	adj[u] = size++;

}



bool spfa()

{

	queue<int> Q;



	memset(in_q, false, sizeof(in_q));

	memset(cnt, 0, sizeof(cnt));

	for (int i = 0; i <= n; i++)

		d[i+1] = -INF;

		

	int u, v, w;

	d[0] = 0;

	Q.push(0);

	in_q[0] = true;



	while (!Q.empty())

	{

		u = Q.front();

		Q.pop();

		in_q[u] = false;



		for (int i = adj[u]; i != -1; i = node[i].next)

		{

			v = node[i].v;

			w = node[i].cost;



			if (d[v] < d[u] + w)

			{

				d[v] = d[u] + w;

				if (!in_q[v])

				{

					in_q[v] = true;

					Q.push(v);

				}



				if (++cnt[v] > n) return false;

			}

		}

	}



	return true;	

}



int main()

{

	int u, v, w;



	while (cin >> n >> m)

	{

		size = 0;

		for (int i = 0; i <= n+1; i++)

			adj[i] = -1;



		int c;

		for (int i = 1; i <= n; i++)

		{

			scanf("%d", &c);

			add_edge(i-1, i, 0);

			add_edge(i, i-1, -c);

		}

		

		for (int i = 1; i <= n; i++)

			add_edge(0, i, 0);



		for (int i = 0; i < m; i++)

		{

			scanf("%d%d%d", &u, &v, &w);

			add_edge(u-1, v, w);		

		}



		if (spfa())

		{

			printf("%d\n", d[n]);

		}

		else

			printf("Bad Estimations\n");

	}

	return 0;

}

你可能感兴趣的:(link)