题意:
给定一个序列的长度,然后给定若干关系,这个关系是子序列各个元素之和与某个给定整数的大小关系。要求是否存在这样一个序列满足所有给定的若干关系。
解析:
设s[i] = a[1] + a[2] + …a[i]。
a[si] + a[si+1] + … + a[si + ni] = s[si + ni] - s[si - 1]。
所以如果a[si] + a[si+1] + … + a[si + ni] < k 则 s[si + ni] - s[si - 1] < k <= k - 1;
如果a[si] + a[si+1] + … + a[si + ni] > k 则 s[si - 1] - s[si + ni] < -k <= -k - 1。
加一个源点0,让每个点与源点0相连,使图联通,然后建图套上差分约束就行了。
spfa 一直wa,bellman过了。
代码:
ac ,bellman:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int maxn = 200 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
int n, m;
struct Edge
{
int fr, to, val;
} e[maxn];
bool Bellman()
{
int dis[maxn];
memset(dis, inf, sizeof(dis));
dis[0] = 0;
for (int i = 0; i <= n; i++)
{
bool over = true;
for (int j = 0; j <= m + n; j++)
{
int fr = e[j].fr;
int to = e[j].to;
int val = e[j].val;
if (dis[fr] + val < dis[to])
{
dis[to] = dis[fr] + val;
over = false;
}
}
if (over)
break;
}
for (int j = 0; j <= m + n; j++)
{
int fr = e[j].fr;
int to = e[j].to;
int val = e[j].val;
if (dis[fr] + val < dis[to])
return true;
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%d", &n) && n)
{
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
int u, v, w;
char op[5];
scanf("%d %d %s %d", &u, &v, op, &w);
if (op[0] == 'g')
{
e[i].fr = u + v + 1;
e[i].to = u;
e[i].val = - w - 1;
}
else
{
e[i].fr = u;
e[i].to = u + v + 1;
e[i].val = w - 1;
}
}
for (int i = 1, j = m; i <= n + 1; i++, j++)
{
e[j].fr = 0;
e[j].to = i;
e[j].val = 0;
}
if (Bellman())
{
printf("successful conspiracy\n");
}
else
{
printf("lamentable kingdom\n");
}
}
return 0;
}
wa, spfa:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int maxn = 200 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
int n, m;
int head[maxn];
bool vis[maxn];
int dis[maxn];
int edgeNum;
struct Edge
{
int fr, to, val;
} e[maxn * 5];
void addedge(int f, int t, int c)
{
e[edgeNum].fr = head[f];
e[edgeNum].to = t;
e[edgeNum].val = c;
head[f] = edgeNum++;
}
bool spfa()
{
int cnt[maxn];
memset(cnt, 0, sizeof(cnt));
memset(dis, inf, sizeof(dis));
memset(vis, false, sizeof(vis));
queue<int> q;
q.push(0);
vis[0] = true;
dis[0] = 0;
while (!q.empty())
{
int cur = q.front();
q.pop();
for (int i = head[cur]; i != -1; i = e[i].fr)
{
int x = e[i].to;
if (dis[cur] + e[i].val < dis[x])
{
dis[x] = dis[cur] + e[i].val;
if (!vis[x])
{
vis[x] = true;
if (++cnt[x] > n)
return true;
q.push(x);
}
}
}
vis[cur] = false;
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%d", &n) && n)
{
scanf("%d", &m);
edgeNum = 0;
memset(head, -1, sizeof(head));
for (int i = 0; i < m; i++)
{
int u, v, w;
char op[5];
scanf("%d %d %s %d", &u, &v, op, &w);
if (op[0] == 'g')
{
addedge(u + v + 1, u, - w - 1);
}
else
{
addedge(u, u + v + 1, w - 1);
}
}
for (int i = 1; i <= n + 1; i++)
{
addedge(0, i, 0);
}
if (spfa())
{
printf("successful conspiracy\n");
}
else
{
printf("lamentable kingdom\n");
}
}
return 0;
}