关于差分约束系统的讲解可以看:http://www.cnblogs.com/void/archive/2011/08/26/2153928.html
这道题只要求判断 aSi + aSi+1 + ... + aSi+ni < ki or aSi + aSi+1 + ... + aSi+ni > ki 是否存在序列 Si = {aSi, aSi+1, ..., aSi+ni},因此,可以用差分约束系统的两种方法做:最长路和最短路,对于建图的方向并没什么要求,s和e点可以互换
一,最长路的代码: 化为:a-b<=c
#include<iostream> #include<cstdio> using namespace std; struct edge { int s,e,v; }e[105]; int dis[105]; const int inf=10000000; int n,m; int bellman(int s) { int i,j; for(i=0;i<=n;i++) dis[i]=inf; dis[s]=0; int flag=1; for(i=0;i<n;i++) { for(j=0;j<m;j++) if(dis[e[j].e]-dis[e[j].s]>e[j].v) dis[e[j].e]=dis[e[j].s]+e[j].v; } for(j=0;j<m;j++) if(dis[e[j].e]-dis[e[j].s]>e[j].v) return 0; return 1; } int main() { char o[5]; while(scanf("%d",&n)!=EOF&&n) { int i,j; int si,ni,ki; scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d%d%s%d",&si,&ni,o,&ki); if(o[0]=='g') { e[i].s=si-1; e[i].e=ni+si; e[i].v=-ki-1; } else { e[i].s=ni+si; e[i].e=si-1; e[i].v=ki-1; } } if(bellman(0)) printf("lamentable kingdom\n"); else printf("successful conspiracy\n"); } return 0; }
#include<iostream> #include<cstdio> using namespace std; struct edge { int s,e,v; }e[105]; int dis[105]; const int inf=10000000; int n,m; int bellman(int s) { int i,j; for(i=0;i<=n;i++) dis[i]=0; dis[s]=0; int flag=1; for(i=0;i<n;i++) { for(j=0;j<m;j++) if(dis[e[j].e]-dis[e[j].s]<e[j].v) dis[e[j].e]=dis[e[j].s]+e[j].v; } for(j=0;j<m;j++) if(dis[e[j].e]-dis[e[j].s]<e[j].v) return 0; return 1; } int main() { char o[5]; while(scanf("%d",&n)!=EOF&&n) { int i,j; int si,ni,ki; scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d%d%s%d",&si,&ni,o,&ki); if(o[0]=='g') { e[i].s=si-1; e[i].e=ni+si; e[i].v=ki+1; } else { e[i].s=ni+si; e[i].e=si-1; e[i].v=-ki+1; } } if(bellman(0)) printf("lamentable kingdom\n"); else printf("successful conspiracy\n"); } return 0; }