POJ1364 SPFA
差分约束
题意:
给出n代表一个序列的长度,给出m个约束条件(si , ni , oi , ki),若oi为gt,则序列从位置si~(si+ni)的和大于ki,若oi为lt,则和小于ki。问是否存在这样的序列使得约束条件成立。
转化为最短路问题:
当 oi 为 gt 时,S(si-1) - S(si+ni) ≤ -k-1
当 oi 为 lt 时, S(si+ni) - S(si-1) ≤ k-1
判断图上是否存在负环
注意点
1.将所有点入队(将图连通)
2.负环判断改成大于入队n+1次
3.顶点从0-n
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
struct edge{int to, next, cost;};
edge e[maxn];
int head[maxn];
int dist[maxn];
int n, m, cnt;
void add_edge(int x, int y, int w)
{
e[cnt].to = y;
e[cnt].next = head[x];
e[cnt].cost = w;
head[x] = cnt;
cnt++;
}
bool spfa(int s)
{
for(int i = 0; i <= n; i++) dist[i] = 0;
int vis[maxn]; memset(vis, 0, sizeof(vis));
bool inque[maxn]; memset(inque, false, sizeof(inque));
queue<int> q;
for(int i = 0; i <= n; i++){
q.push(i);vis[i]++; inque[i] = true;
}
while(!q.empty()){
int cur = q.front(); q.pop(); inque[cur] = false;
for(int i = head[cur]; ~i; i = e[i].next){
if(dist[e[i].to] > dist[cur] + e[i].cost){
dist[e[i].to] = dist[cur] + e[i].cost;
if(!inque[e[i].to]){
q.push(e[i].to); inque[e[i].to] = true;
if(++vis[e[i].to] > n+1) return false;
}
}
}
}
return true;
}
int main()
{
cnt =0;
while(cin>>n){
if(!n) break;
cin>>m;
memset(head, -1, sizeof(head));
for(int i = 0; i < m; i++){
int x, y, w; string t;
cin>>x>>y>>t>>w;
if(t == "gt") add_edge(x-1, x+y, -w-1);
else add_edge(x+y, x-1, w-1);
}
if(!spfa(0)) cout<<"successful conspiracy"<<endl;
else{
cout<<"lamentable kingdom"<<endl;
}
}
return 0;
}