poj 1364 King (Bellman_ford+差分约束)
从开始学习差分约束到现在也应经做过几道题了,但是在做这道题的时候突然就不知道差分约束到底是来干嘛的了,很郁闷,用重新看了一遍《算法导论》上的讲解,然后有浏览了一下自己做过的题,终于是明白了那么点~~
其实说到底,差分约束就是给你N个不等式,让你求一下是不是有一组N维的矩阵使这些不等式都成立,而这个N维矩阵是不确定,所以所有的差分约束题不是让你判断是否可能实现,就是让你求出xn-xi的最大值,最小值什么的,从来不会让你求出符合要求的一组解,或许会有,是我还没做到,而之所以要用求最短路的各种方法来求解就是因为要求解的不等式形式和最短路中的不等式形式相识,所以那些方法既然能求最短路,自然能求这些不等式,所以差分约束和最短路根本是两回事,我觉得做差分约束题最难的部分就是建图,这时有各方面原因造成,首先英语不好,读题都很困难,更何况还要提取题目中的有用信息呢,再者,不善于发现,总是想依靠于题目中给的要求去做,不去细想隐藏的条件。。。好了,说得再多,不如做的多,以后努力改正。。。
下面来说说这题:
题意:对题目中给定的si,ni,ki,和一个给定的序列S[1....N] 如果(si,ni,gt,ki),意思就是存在约束条件S[ai]+S[ai+1]+...S[ai+ni] > ki 如果(si,ni,lt,ki),意思就是存在约束条件S[ai]+S[ai+1]+...S[ai+ni] < ki 判断所给的约束条件有无解,有解就输出lamentable kingdom,无解就输出successful conspiracy 。
思路:其实这题只要找对了不等式,那就完事,对时间和内存的要求不高,哪种方法都可以过,关键是找不等式,假设s[n] 表示ai前n项的和,则:
s[ai+n] - s[ai] < ki
s[ai+n] - s[ai] > ki
又差分约束系统的求解只能针对>=或<=,无法求解>的系统,还好ki是整数,可以很容易将<转化为<=
s[ai+n] - s[ai] <= ki -1
s[ai] - s[ai+n] <= -ki - 1
然后就是代码了:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #define N 105 #define INF 100000000 using namespace std ; struct node { int si ; int ei ; int val ; }p[N] ; int dis[N] ; int mark[N] , num[N] ; int n , m ; int q[N] , top ; int Bellman_ford ( int s0 ) { int i , j ; memset( dis , 0 , sizeof ( dis )); for ( i = 0 ; i < n ; i++ ) { for ( j = 0 ; j < m ; j++ ) if ( dis[p[j].ei] > dis[p[j].si] + p[j].val ) dis[p[j].ei] = dis[p[j].si] + p[j].val ; } for ( i = 0 ; i < m ; i++ ) if ( dis[p[i].ei] > dis[p[i].si] + p[i].val ) return 0 ; return 1 ; } int main() { int i , j , x , y , z ; char ch[5] ; while ( scanf ( "%d" , &n ) , n ) { scanf ( "%d" , &m ); for ( i = 0 ; i < m ; i++ ) { scanf ( "%d%d %s%d" , &x , &y , ch , &z ); //cout<<ch<<endl; if ( ch[0] == 'g' ) { p[i].si = x + y ; p[i].ei = x - 1; p[i].val = -1 - z ; } else { p[i].si = x - 1 ; p[i].ei = x + y ; p[i].val = z - 1 ; } } if ( Bellman_ford ( 1 )) printf ( "lamentable kingdom\n" ); else printf ( "successful conspiracy\n" ); } return 0 ; }