您的位置:首页 > 其它

POJ 1364 King 【差分约束 + 判环模型】

2018-02-02 20:27 477 查看
传送门

/ 题意:

n个数的一个序列,m个约束,

si, ni, oi, ki, 代表了序列中第si个数到第si+ni个数的和大于或小于ki, oi = gt = 大于, oi = lt = 小于

问是否存在相悖的约束

// 思路: 很明显的不等式, 再看问题即可知道就是差分约束.

约束已经很明显了设sum[i]为前i个数的和,那么就可以得到约束:si, ni, gt, ki , 因为是小于, 然后又是在整数域, 所以我们做等于的情况.

sum[0] = 0

oi为gt时:sum[si+ni] - sum[si-1] >= ki+1

oi为lt时:sum[si+ni] - sum[si-1] <= ki-1

然后就是建图, 求1 - n 的最短路, 如果不满足国王的逻辑, 则这幅图中一定存在负环.

注: 因为我跑的最短路, 所以就是直接判有无负环, 所以dis的初始值都要是inf, 还有就是有可能建的这幅图不连通, 所以判不到负环去, 所以要把所有的点都推进队列去找. 只要有一个有负环就不满足国王的逻辑. 因为推进了所有的点, 所以所有的距离都是inf, 只要有负环的话始终会进队列的, 因为我们加的里面有负权边呀!!!

// 因为我是以 <= 为准, 所以我们跑最短路, 判负环, 当然以 >= 为准也行, 这是就是跑最长路, 判正环, 总之一定要根据你定的那个标准为准.

AC Code

const int maxn=1e5+5;
const int inf = 0x3f3f3f3f; //用这个可以直接mem
int cas = 1;
int n,m;
int head[maxn], cnt, dis[maxn];
bool vis[maxn];
int times[maxn];
struct node
{
int to,next,w;
}e[maxn<<1];
void add(int u, int v, int w)
{
e[cnt] = (node){v,head[u],w};
head[u] = cnt++;
}
void init() {
cnt = 0 ;
Fill(head, -1);
}
bool spfa(int st,int ed)
{
Fill(dis, inf); Fill(vis, 0);
queue<int >q; Fill(times, 0);
for(int i=0;i<=n;i++){
q.push(i);     //每个点都要进去.
vis[i] = true;
times[i]++;
}
q.push(st);  // dis距离全是inf.
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; ~i ;i = e[i].next){
int to = e[i].to;
//因为我定的是小于, 所以我跑最短路.由于每个点都在队列,所以dis的值都是inf
// 有负权边的话始终会进去, 有负环的话始终会多次入队,
if(dis[to] > dis[u] + e[i].w){
dis[to] = dis[u] + e[i].w;
if(times[to] > n)
return false;
else if(!vis[to]){
times[to]++;
vis[to] = true;
q.push(to);
}
}
}
}
return true;
}

void solve()
{
while(~scanf("%d",&n) && n){
scanf("%d",&m);
init();
for(int i=1;i<=m;i++){
int u, v, w; string s;
cin >> u >> v >> s >> w;
if(s == "gt"){   //gt代表大于.
add(u+v, u-1, -(w+1)); //而路肯定是要取等于的.所以应该取>=
}
else add(u-1, u+v, w-1); //lt代表小于.
}
if(spfa(1,n)) printf("lamentable kingdom\n");
else printf("successful conspiracy\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: