您的位置:首页 > 其它

zoj 2770 Burn the Linked Camp(火烧连营) 差分约束

2018-02-02 16:03 253 查看
今天学了一个东西叫差分约束,简单来说就是用最短路知识的三角不等式来解多元不等式组。假设 Xv - Xu <= e 可利用最短路的三角不等式将这个不等式转化为图中的一条边,这条单向边是以u为起点,V为终点,权值为e。若将不等式组中的所有边建图。就可将解不等式问题转化成图的最短路问题。

但是难点在于如何根据已知条件构造不等式组,这是难点,也是解决问题的关键。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 1000 + 10; // 点数
const int MAX = 0x3f3f3f3f;
int c[MAXN]; //记录每个兵营的最大人数
int dp[MAXN]; // 记录兵营最大人数的前缀和,构造的核心与关键。
struct Edge
{
int u,v,w;
};
Edge e[30100];
int dis[MAXN];
int n,m;
bool bellman_ford()
{
memset(dis,MAX,sizeof(dis));
dis
= 0;
for(int i = 0;i <= n - 1;++i)//注意循环次数,点数其实是n + 1
{
for(int j = 1;j <= m;++j)
{
dis[e[j].v] = min(dis[e[j].v],dis[e[j].u] + e[j].w);
}
}
for(int i = 1; i <= m;++i) // 存在无解的情况。
{
if(dis[e[i].v] > dis[e[i].u] + e[i].w)
{
return 0;
}
}
return 1;
}

int main()
{
while(cin >> n >> m)
{
int cnt = 1;
memset(dp,0,sizeof(dp)); // dp初始化
for(int i = 1;i <= n; ++i)
{
cin >> c[i];
dp[i] = dp[i - 1] + c[i];
}
{
int a,b,w;
cin >> a >> b >> w;
e[cnt].u = b;
e[cnt].v = a - 1;
e[cnt].w = -w;
cnt++;
e[cnt].u = a - 1;
e[cnt].v = b;
e[cnt].w = abs(dp[a - 1] - dp[b]);
cnt++;
}
for(int i = 0;i <= n - 1;++i) //
{
e[cnt].u = i;
e[cnt].v = i + 1;
e[cnt].w = c[i + 1];
cnt++;
e[cnt].u = i + 1;
e[cnt].v = i;
e[cnt].w = 0;
cnt++;
}
m = cnt - 1;
bool tag;
tag = bellman_ford();
if(!tag)
cout << "Bad Estimations" << endl;
else
cout << dis
- dis[0] << endl;
}
return 0;
}


总结:

用前缀和构造点的原因在于构造,首先是利用条件并且是构造出差的那种形式,结合题意“和“这个东西是思考方向/。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: