// // // // // // // // // // // // // //

关于差分约束

差分约束系统

1. Intervals

/*
  Time: 1.31
  Worker: Blank_space
  Source: #10087. 「一本通 3.4 例 1」Intervals
  建图 单源最长路 
  注意上下界的约束 
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define emm(x) memset(x, 0x8f, sizeof x)
using namespace std; 
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
struct edge {int v, w;};
vector <edge> e[B];
int n, s = INF, t, dis[B];
queue <int> q;
bool vis[B];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
int min(int x, int y) {return x < y ? x : y;}
int max(int x, int y) {return x > y ? x : y;}
/*----------------------------------------函数*/
int main()
{
    n = read();
    for(int i = 1; i <= n; i++)
    {
    	int x = read() - 1, y = read(), z = read();
    	s = min(x, s); t = max(t, y);
    	e[x].push_back((edge){y, z});
    }
    for(int i = s; i <= t; i++) e[i].push_back((edge){i + 1, 0}), e[i + 1].push_back((edge){i, -1});
    fill(dis + 1 + s, dis + 1 + t, -INF);
	dis[s] = 0; q.push(s);
    while(!q.empty())
    {
    	int u = q.front(); q.pop(); vis[u] = 0;
    	for(int i = 0; i < e[u].size(); i++)
    	{
    		int v = e[u][i].v, w = e[u][i].w;
    		if(dis[v] < dis[u] + w)
    		{
    			dis[v] = dis[u] + w;
    			if(!vis[v]) {vis[v] = 1; q.push(v);}
    		}
    	}
    }
    printf("%d", dis[t]);
	return 0;
}

2. 出纳员问题

/*
  Time: 1.31
  Worker: Blank_space
  Source: #10088. 「一本通 3.4 例 2」出纳员问题	
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define emm(x) memset(x, 0, sizeof x)
#define emmm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
struct edge {int v, w;};
vector <edge> e[A];
int T, n, R[A], num[A], _c[A], c[A], dis[A], cnt, ans = INF;
bool vis[A], p;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
bool check(int x)
{
	emm(e); emmm(dis); emm(vis); cnt = 0; e[0].push_back((edge){24, x});
	for(int i = 1 ; i <= 24 ; i++)
	{
		e[i].push_back((edge){i - 1, 0}); 
		e[i - 1].push_back((edge){i, num[i]}); 
		if(i > 8) e[i].push_back((edge){i - 8, -R[i]});
		else e[i].push_back((edge){i + 16, x - R[i]});
	}
	queue <int> q;
	q.push(0); dis[0] = 0;
	while(!q.empty())
	{
		int u = q.front(); q.pop(); vis[u] = 0;
		for(int i = 0; i < e[u].size(); i++) 
		{
			int v = e[u][i].v, w = e[u][i].w;
			if(dis[v] > dis[u] + w)
			{
				dis[v] = dis[u] + w; cnt++;
				if(!vis[v]) {vis[v] = 1; q.push(v);}
				if(cnt > 2000) return 0;
			}
		}
	}
	return dis[24] == x;
}
void work()
{
	emm(R); emm(c); emm(num); ans = INF;
	for(int i = 1; i <= 24; i++) R[i] = read();
	n = read();
	for(int i = 1; i <= n; i++) {int x = read() + 1; num[x]++;}
	int l = 0, r = n;
	while(l <= r)//二分最终人数 
	{
		int mid = l + r >> 1;
		if(check(mid)) ans = mid, r = mid - 1;
		else l = mid + 1;
	}
	if(ans == INF) puts("No Solution");
	else printf("%d\n", ans);
}
/*----------------------------------------函数*/
int main()
{
//	freopen("Cashier.in", "r", stdin); 
    T = read();
    while(T--) work();
	return 0;
}

3. 糖果

/*
  Time: 1.31
  Worker: Blank_space
  Source: #2436. 「SCOI2011」糖果
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define ll long long
#define emm(x) memset(x, 0, sizeof x)
#define emmm(x) memset(x, 0x8f, sizeof x)
using namespace std; 
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
struct edge {int v, w;};
vector <edge> e[B << 1];
int n, k, cnt, tot[B];
ll dis[B], ans;
bool vis[B];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
int main()
{
    n = read(); k = read();
    for(int i = 1; i <= k; i++)
    {
    	int x = read(), a = read(), b = read();
    	if(!(x & 1) && a == b) {puts("-1"); return 0;}
    	if(x == 1) e[b].push_back((edge){a, 0}), e[a].push_back((edge){b, 0});
    	if(x == 2) e[a].push_back((edge){b, 1});
    	if(x == 3) e[b].push_back((edge){a, 0});
    	if(x == 4) e[b].push_back((edge){a, 1});
    	if(x == 5) e[a].push_back((edge){b, 0});
    }
    for(int i = 1; i <= n; i++) e[0].push_back((edge){i, 1});
    queue <int> q;
    q.push(0); dis[0] = 0;
    while(!q.empty())
    {
    	int u = q.front(); q.pop(); vis[u] = 0;
    	if(tot[u] == n - 1) {puts("-1"); return 0;}
    	tot[u]++;
    	for(int i = 0; i < e[u].size(); i++)
    	{
    		int v = e[u][i].v, w = e[u][i].w;
    		if(dis[v] < dis[u] + w)
    		{
    			dis[v] = dis[u] + w;
    			if(!vis[v]) {vis[v] = 1; q.push(v);}
    		}
    	}
    }
    for(int i = 1; i <= n; i++) ans += dis[i];
    printf("%lld", ans);
	return 0;
}

4. 排队布局

/*
  Time: 1.31
  Worker: Blank_space
  Source: #10090. 「一本通 3.4 练习 2」布局 Layout
  直接分开写 spfa宽搜判环效率比较感人 
  开 long long 
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define ll long long 
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
struct edge {int v, w;};
vector <edge> e[1010];
int n, m1, m2, dis1[1010], vis1[1010];
ll dis2[1010];
bool vis2[1010], p;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void dfs(int u, int tp)
{
	if(p) return ;
	vis1[u] = tp;
	for(int i = 0, lim = e[u].size(); i < lim; i++)
	{
		int v = e[u][i].v, w = e[u][i].w;
		if(dis1[v] <= dis1[u] + w) continue;
		dis1[v] = dis1[u] + w;
		if(!vis1[v]) dfs(v, tp);
		if(p) return ;
		else if(vis1[v] == tp) {p = 1; return ;}
	}
	vis1[u] = 0;
}
/*----------------------------------------函数*/
int main()
{
    n = read(); m1 = read(); m2 = read();
    for(int i = 1; i <= m1; i++)
    {
    	int x = read(), y = read(), z = read();
    	e[x].push_back((edge){y, z});
    }
    for(int i = 1; i <= m2; i++)
    {
    	int x = read(), y = read(), z = read();
    	e[y].push_back((edge){x, -z});
    }
    for(int i = 2; i <= n; i++) e[i].push_back((edge){i - 1, 0});
    for(int i = 1; i <= n; i++) {dfs(i, i); if(p) {puts("-1"); return 0;}}
    for(int i = 1; i <= n; i++) e[0].push_back((edge){i, 0});
    dfs(0, 0); if(p) {puts("-1"); return 0;}
    for(int i = 1; i <= n; i++) dis2[i] = 1e13 + 7;
    queue <int> q;
    q.push(1); dis2[1] = 0;
    while(!q.empty())
    {
    	int u = q.front(); q.pop(); vis2[u] = 0;
    	for(int i = 0, lim = e[u].size(); i < lim; i++)
    	{
    		int v = e[u][i].v, w = e[u][i].w;
    		if(dis2[v] > dis2[u] + w)
    		{
    			dis2[v] = dis2[u] + w;
    			if(!vis2[v]) {vis2[v] = 1; q.push(v);}
    		}
    	}
    }
    if(dis2[n] == 1e13 + 7) puts("-2");
    else printf("%lld", dis2[n]);
	return 0;
}


——end

posted @ 2021-02-01 09:28  Blank_space  阅读(64)  评论(0)    收藏  举报
// // // // // // //