Arhus University 2000 - King (差分约束)
题目链接:传送门
题意:
对题目中给定的si,ni,gi,ki,和一个给定的序列S[1....N],如果格式为(si,ni,gt,ki),意思就是新增一约束条件S[si]+S[si+1]+...S[si+ni]>ki,如果格式为(si,ni,lt,ki),意思就是新增一约束条件S[si]+S[si+1]+...S[si+ni]<ki,判断所给的约束条件有符合要求的序列S[1....N],有解就输出lamentable kingdom,无解就输出successful conspiracy。
题解:
1. 对于gt,根据约束条件 S[si]+S[si+1]+...S[si+ni] > ki 可以列出 d[si+ni] - d[si-1] > ki ,即为 d[si-1] - d[si+ni] <= ki
2. 对于lt ,根据约束条件 S[si]+S[si+1]+...S[si+ni] < ki 可以列出 d[si+ni] - d[si-1] < ki ,即为 d[si+ni] - d[si-1] <= ki - 1
3. 新增点n+1,建立n+1到(1~n)的边,权值为0
最后spfa判是否存在负环即可,条件为sum[to]>=n+2
代码:
链式前向星&spfa
#include<bits/stdc++.h> #define numm ch-48 #define pd putchar(' ') #define pn putchar('\n') #define pb push_back #define fi first #define se second #define fre1 freopen("1.txt","r",stdin) #define fre2 freopen("2.txt","w",stdout) using namespace std; template <typename T> void read(T &res) { bool flag=false;char ch; while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); flag&&(res=-res); } template <typename T> void write(T x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } const int maxn=110; const int inf=0x3f3f3f3f; typedef long long ll; struct edge { int to,w,net; }edge[maxn]; int k,dis[maxn]; int sum[maxn],head[maxn],vis[maxn]; void init() { k=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); memset(sum,0,sizeof(sum)); memset(dis,inf,sizeof(dis)); } void add(int u,int v,int w) { edge[++k].to=v; edge[k].w=w; edge[k].net=head[u]; head[u]=k; } bool spfa(int n) { dis[n+1]=0,sum[n+1]++; queue<int>que; que.push(n+1); while(!que.empty()) { int k=que.front(); que.pop(); vis[k]=false; for(int i=head[k];i!=-1;i=edge[i].net) { if(dis[edge[i].to]>edge[i].w+dis[k]) { dis[edge[i].to]=edge[i].w+dis[k]; if(!vis[edge[i].to]) { if(++sum[edge[i].to]>=n+2) return false; que.push(edge[i].to); vis[edge[i].to]=true; } } } } return true; } int main() { int n,m; while(scanf("%d",&n)!=EOF&&n) { read(m); init(); for(int i=1;i<=m;i++) { int si,ni,ki; char oi[4]; read(si),read(ni); scanf("%s",oi); read(ki); oi[0] == 'g' ? add(si+ni,si-1,-ki-1) : add(si-1,si+ni,ki-1); } for(int i=0;i<=n;i++) add(n+1,i,0); // puts("sadas"); puts(spfa(n) ? "lamentable kingdom" : "successful conspiracy"); } return 0; }
所谓人生,一半惊喜,一半遗憾