标签:差分约束 bellman_ford
题目地址:POJ 1364
题意:n个数的一个序列,m个约数,si, ni, oi, ki, 代表了序列中第si个数到第si+ni个数的和大于或小于ki,gt 为大于,lt 为 小于。问是否存在相悖的约束。
思路:
因为这个题目是单纯的大于或者小于,所以要变成大于等于或者小于等于,这样的话就在k值的基础上+1或者-1。所以就有了以下的约束。
设sum[i]为前i个数的和,那么就可以得到约束:si, ni, oi, ki
sum[0] = 0
oi为gt时:sum[si-1] - sum[si+ni] <= ki+1
oi为lt时:sum[si+ni] - sum[si-1] <= ki-1。
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set> #include <queue> #include <stack> #include <map> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const double pi= acos(-1.0); const double esp=1e-6; const int maxn=210; int n,m,cnt; int head[maxn]; int dis[maxn]; struct node { int u,v,w; int next; }edge[1000010]; void add(int u,int v,int w) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } int Bellman_ford(int n) { int i,j; memset(dis,0,sizeof(dis)); dis[1]=0; for(i=1;i<=n;i++){ int flag=0; for(j=0;j<cnt;j++){ int u=edge[j].u; int v=edge[j].v; if(dis[v]>dis[u]+edge[j].w){ dis[v]=dis[u]+edge[j].w; flag=1; } } if(!flag) break; } for(i=0;i<cnt;i++){ if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w) return 0; } return 1; } int main() { char str[10]; int u,v,w; while(~scanf("%d",&n)){ if(!n) break; scanf("%d",&m); memset(head,-1,sizeof(head)); cnt=0; while(m--){ scanf("%d %d %s %d",&u,&v,str,&w); if(str[0]=='g'){ add(u+v,u-1,-w-1); } else{ add(u-1,u+v,w-1); } } int ans=Bellman_ford(n); if(ans) puts("lamentable kingdom"); else puts("successful conspiracy"); } return 0; }
标签:差分约束 bellman_ford
原文地址:http://blog.csdn.net/u013486414/article/details/46377503