【POJ】1364 King
2015-07-29 19:48
281 查看
【解析】查分约束系统,最短路
[Problem]
S={a1,a2,a3,a4...ai...at},其中ai=a*si
现在给出多个不等式,使得ai+a[i+1]+a[i+2]+...+a[i+n]<ki或>ki
不等式这样描述:
给出四个参数i,n,s,d,i表示从序列的第i项开始,n表示序列长度为n,
当s="gt"时,表示A=ai+a[i+1]+...+a[i+n]>d,否则当s="lt"时,A<d。
询问是否有解。
[Analysis]
首先a*si可以不用管,谁知道a是多少呢,特殊值a=1就可以了。
由于是静态区间,考虑差分的思想,设tr[i]=∑a[j],1<=j<=i。
然后每一个约束条件都可以用差分的形式表示。
对于给定的i,n,s,d,
①当s="gt"时,
a[i]+a[i+1]+...+a[i+n]=tr[i+n]-tr[i-1]>d
∴tr[i+n]>d+tr[i-1]
∴tr[i-1]+(d+1)<=tr[i+n](式1)
建边(i-1,i+n,d+1)。
②当s="lt"
a[i]+...+a[i+n]=tr[i+n]-tr[i-1]<d
∴tr[i+n]+(1-d)<=tr[i-1]
建边(i+n,i-1,1-d)。(式2)
然后就求最长路看看有没有正权回路。(其实正负是差不多的,假如求负权回路就换一种建图方式)
至于为什么是正权回路而不是负权回路,这是为了满足每个约束条件,假如选了最短路,那么可能就会存在约束条件不满足。
用(式1)(式2)来理解。
接下来是求负权回路的方法。
求负权回路就用最短路的算法解决。
SPFA:设个数组vis,由于每个点不可能被松弛超过n次,所以当vis=n时就退出。
Bellman-Ford:O(n^3),稳定,代码短,具体就是枚举松弛次数,然后枚举两个点看看能不能松弛,最后再判断一次。
[Sum]
①回顾了查分约束系统的建图和求解。
②特别注意,用SPFA要n+1次的时候再判断不行。
[Problem]
S={a1,a2,a3,a4...ai...at},其中ai=a*si
现在给出多个不等式,使得ai+a[i+1]+a[i+2]+...+a[i+n]<ki或>ki
不等式这样描述:
给出四个参数i,n,s,d,i表示从序列的第i项开始,n表示序列长度为n,
当s="gt"时,表示A=ai+a[i+1]+...+a[i+n]>d,否则当s="lt"时,A<d。
询问是否有解。
[Analysis]
首先a*si可以不用管,谁知道a是多少呢,特殊值a=1就可以了。
由于是静态区间,考虑差分的思想,设tr[i]=∑a[j],1<=j<=i。
然后每一个约束条件都可以用差分的形式表示。
对于给定的i,n,s,d,
①当s="gt"时,
a[i]+a[i+1]+...+a[i+n]=tr[i+n]-tr[i-1]>d
∴tr[i+n]>d+tr[i-1]
∴tr[i-1]+(d+1)<=tr[i+n](式1)
建边(i-1,i+n,d+1)。
②当s="lt"
a[i]+...+a[i+n]=tr[i+n]-tr[i-1]<d
∴tr[i+n]+(1-d)<=tr[i-1]
建边(i+n,i-1,1-d)。(式2)
然后就求最长路看看有没有正权回路。(其实正负是差不多的,假如求负权回路就换一种建图方式)
至于为什么是正权回路而不是负权回路,这是为了满足每个约束条件,假如选了最短路,那么可能就会存在约束条件不满足。
用(式1)(式2)来理解。
接下来是求负权回路的方法。
求负权回路就用最短路的算法解决。
SPFA:设个数组vis,由于每个点不可能被松弛超过n次,所以当vis=n时就退出。
Bellman-Ford:O(n^3),稳定,代码短,具体就是枚举松弛次数,然后枚举两个点看看能不能松弛,最后再判断一次。
[Sum]
①回顾了查分约束系统的建图和求解。
②特别注意,用SPFA要n+1次的时候再判断不行。
#include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int N=160; const int MAX=20000000; int n,m; struct G { int v,d,nxt; }map ; int tt,hd ; int q ,h,t,used ,vis ,d ; inline int read(void) { int s=0,f=1; char c=getchar(); for (;c<'0'||c>'9';c=getchar()) if (c=='-') f=-1; for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-'0'; return s*f; } void ins(int u,int v,int d) { map[++tt].v=v; map[tt].d=d; map[tt].nxt=hd[u]; hd[u]=tt; } void build(void) { int x,y,d; char c; tt=0; memset(hd,0,sizeof hd); for (int i=1;i<=m;i++) { scanf("%d%d %ct %d",&x,&y,&c,&d); if (c=='g') ins(x+y,x-1,d+1); else ins(x-1,x+y,1-d); } for (int i=0;i<=n;i++) ins(n+1,i,0); n++; } void spfa(void) { h=t=0; memset(vis,0,sizeof vis); memset(used,0,sizeof used); for (int i=0;i<=n;i++) d[i]=-MAX; d =0,vis =1,used =1,q[t=1]=n; int k; for (;h^t;) { k=q[h=h%(n+1)+1]; for (int r=hd[k];r;r=map[r].nxt) if (d[k]+map[r].d>d[map[r].v]) { d[map[r].v]=d[k]+map[r].d; vis[map[r].v]++; if (vis[map[r].v]==n+1) { printf("successful conspiracy\n"); return; } if (!used[map[r].v]) { used[map[r].v]=1; q[t=t%(n+1)+1]=map[r].v; } } used[k]=0; } printf("lamentable kingdom\n"); } int main(void) { for (int cc=1;cc;cc++) { n=read(); if (!n) break; m=read(); build(); spfa(); } return 0; }
相关文章推荐
- POJ 2965 The Pilots Brothers' refrigerator (想法题)
- vs2015安装使用体验
- CFrameWnd的两个函数
- HDOJ 3966 Aragorn's Story
- 快速排序 c++
- hdu 5325 Crazy Bobo (树形dp)
- 关于cassandra vnode的理解-marsyoung.
- 排序算法的稳定性讨论
- 【CodeForces】E. Xenia and Tree(分块 + LCA)
- Trim(),TrimStart(),TrimEnd()用于去除字符串中的特定字符
- 多校第三场 1010 hdu 5325 Crazy Bobo(拓扑排序+树形dp)
- linux防火墙基础和管理设置iptables规则
- java中的并发:线程通信
- 脚本学习之路之----我要熟悉awk, sed, rpm 工具
- 简单明了的明白进程和线程的区别
- 【dp】【bzoj 1079】【SCOI 2008】着色方案
- ExQuilla的使用和破解
- E 接口
- 使用freemarker中的小数点处理的一点心得!
- PHP获取当前页面的URL作为参数以供下一层的页面可以返回上一层页面