算法:差分约束
设Sum(i)=a1+a2+...+ai
任何一个序列
aSi + aSi+1 + ... + aSi+ni
可以变成 Sum(Si+ni)-Sum(Si-1)
然后如果是>号就两边乘-1,>号就变<号了
最后就是把<号变成<=号,因为所有数都是整数,把右边的数字-1就行了……
然后就化成标准的差分约束了
CODE:
/*AC代码:0ms*/ #include <iostream> #include <queue> #include <cstring> using namespace std; #define INF 0x7fffffff #define MAXN 150 int map[MAXN][MAXN];//用来存约束图 bool flag[MAXN][MAXN];//flag[u][v]判断u->v是否有边 int visited[MAXN];//被松弛的次数 int d[MAXN];//d[v]表示源点到v点的最短路径 int N,M;//N是序列长度,M是约束条件个数 void init()//输入 { int si,ni,ki,i; int hx,hy,b; char w[3]; memset(map,0,sizeof(map)); memset(flag,false,sizeof(flag)); N++; while(M--) { scanf("%d%d%s%d",&si,&ni,w,&ki); si++;//注意点, if(w[0]=='g') { hx=si-1; hy=si+ni; b=-ki-1; } else { hx=si+ni; hy=si-1; b=ki-1; } map[hx][hy]=b; flag[hx][hy]=true; //---------------// //这个也能A的 //map[hy][hx]=b; //flag[hy][hx]=true; } for(i=1;i<=N;i++)//增加的0点于所有其他点都有权为0的边,目的确保整张图变通 flag[0][i]=true; } bool Bellman_Ford() { int i,temp; queue<int>Q; memset(visited,0,sizeof(visited)); //memset(d,INF,sizeof(d));不能用 for(i=1;i<=N;i++) d[i]=INF; d[0]=0; visited[0]++; Q.push(0); while(!Q.empty()) { temp=Q.front(); Q.pop(); for(i=0;i<=N;i++)//用temp点更新其他点 { if(flag[temp][i]) { if(d[temp]+map[temp][i]<d[i]) { d[i]=d[temp]+map[temp][i]; Q.push(i); visited[i]++; if(visited[i]>N)//被松弛的次数超过N,说明存在负权回路 return false; } } } } return true; } int main() { while(scanf("%d",&N)!=EOF) { if(N==0) break; scanf("%d",&M); init();//输入函数 if(Bellman_Ford()) printf("lamentable kingdom\n"); else printf("successful conspiracy\n"); } return 0; }