poj 1364 King 差分约束
这题再次对差分约束的超源点有了新的理解。
设d[i] = a[1] + …+a[i],根据题意有:
d[si + ni] – d[si-1] >= k + 1
d[si+ni] – d[si-1] <= k - 1 即 d[si-1] – d[si+ni] >= 1 – k
通过求最长路来判断图中是否存在正环。
这题可以通过加超源点,或者不加,加超源点不好想
使用bellman算法,这个不需要加超源点,但要注意,每条边要松弛n次,而不是n-1次,因为图的顶点是从0~n的,开始没注意,WA好多次。
使用spfa算法,这里如果不添加超源点的话,要先把所有点都入队,再进行松弛,这样保证,每个点都得到检查。
而添加超源点,加设添加超源点a[n+1], a[n+1]是无穷小的数,即-INF, 它与前面的a[1] ~ a[n] 之和也是无穷小的,即s[n+1] = –INF。从而s[n+1] – s[i] <= 0不等式成立,即有 s[i] – s[n+1] >= 0, (i = 1,2,..,n), 再以n+1为源点开始搜索,这样得到的解,除了满足题设的要求外,还满足了不等式s[i] – s[n+1] >= 0, 因为a[n+1]任我们假设的,因此添加了这个不等式对题目没有任何影响。
#include<iostream>
#include <queue>
using namespace std;
const int MAX = 1000;
const int INF = 1000000000;
struct Node
{
int v;
int cost;
int next;
};
Node node[MAX];
int d[MAX];
int adj[MAX];
bool in_q[MAX];
int cnt[MAX];
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(cnt, 0, sizeof(cnt));
memset(in_q, false, sizeof(in_q));
for (int i = 0; i <= n; i++)
d[i] = -INF;
//添加一个为n+1的超源点
for (int i = 0; i <= n; i++)
add_edge(n+1, i, 0);
//d[n+1] = 0; 这句不能加,因为d[n+1]是为-INF,是无限小的数
in_q[n+1] = true;
Q.push(n+1);
int u, v, w;
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;
}
bool bellman_ford()
{
int v, w;
bool isfinish;
//这里需要松弛n次,而不是n-1次,不然会WA
//因为这里的顶点数是从0~n共n+1个, 0也是有意义的。
for (int i = 1; i <= n; i++)
{
isfinish = true;
for (int u = 0; u <= n; u++)
for (int k = adj[u]; k != -1; k = node[k].next)
{
v = node[k].v;
w = node[k].cost;
if (d[u] < d[v] + w)
{
d[u] = d[v] + w;
isfinish = false;
}
}
if (isfinish) break;
}
for (int u = 0; u <= n; u++)
for (int k = adj[u]; k != -1; k = node[k].next)
{
v = node[k].v;
w = node[k].cost;
if (d[u] < d[v] + w)
return false;
}
return true;
}
int main()
{
char c[10];
int a, b, w;
while (scanf("%d", &n))
{
if (n == 0) break;
scanf("%d", &m);
for (int i = 0; i <= n+1; i++)
adj[i] = -1;
size = 0;
for (int i = 0; i < m; i++)
{
scanf("%d %d %s %d", &a, &b, c, &w);
if (strcmp(c, "gt") == 0)
add_edge(a-1, a+b, w+1);
else
add_edge(a+b, a-1, 1-w);
}
if (spfa())
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return 0;
}
浙公网安备 33010602011771号