POJ 1364 King[差分约束]
题目链接:http://poj.org/problem?id=1364
题目大意:是否存在一个序列满足给的m组条件
si ni oi ki
如果oi=gt 表示:S(i+ni)-Si>ki
如果oi=lt 表示:S(i+ni)-Si<ki
由于查分约束的特点要变成x-y<=z的形势,因此对于上面的式子变形:
oi=gt ---> S(i+ni)-Si<=-ki-1
oi=lt ---> Si-S(i+ni)<=ki-1
然后建图,用spfa求最短路
代码如下:
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define N 100000 #define M 100000 #define INF 999999999 int dis[N]; //记录距离 int vis[N]; //标记是否在队列中 int queue[N]; //模拟队列 int outqueue[N]; //记录点i出队的次数 int head[N]; int index, n; //index记录head[] s:源点 n个点 struct Edge { int v, next, value; }edge[M]; void add_Edge(int u, int v, int val) { edge[index].next=head[u]; edge[index].v=v; edge[index].value=val; head[u]=index++; } int Spfa(int s) { int iq=0, front=0, i, top; memset(vis, 0, sizeof(vis)); memset(outqueue, 0, sizeof(outqueue)); for(i=0; i<=n; i++) dis[i]=INF; dis[s]=0; queue[iq++]=s; vis[s]=1; while(iq!=front) { top=queue[front]; front++; vis[top]=0; outqueue[top]++; if(outqueue[top]>n) return 0; for(i=head[top]; i!=-1; i=edge[i].next) { if(dis[top]+edge[i].value<dis[edge[i].v]) { dis[edge[i].v]=dis[top]+edge[i].value; if(vis[edge[i].v]==0) { vis[edge[i].v]=1; queue[iq++]=edge[i].v; } } } } return 1; } int main() { int si, ki, i, ni, m; char ch[5]; while(scanf("%d", &n), n) { scanf("%d", &m); index=0; memset(head, -1, sizeof(head)); for(i=0; i<m; i++) { scanf("%d %d %s %d", &si, &ni, ch, &ki); if(ch[0]=='g') add_Edge(ni+si, si-1, -ki-1); else add_Edge(si-1, ni+si, ki-1); } for(i=1; i<=n; ++i) //i=0开始一直wa...wa死我了...泪奔TT... add_Edge(n+1, i, 0); if(Spfa(n+1)) printf("lamentable kingdom\n"); else printf("successful conspiracy\n"); } return 0; }