poj1364 King

来源:互联网 发布:淘宝卖变声软件吗 编辑:程序博客网 时间:2024/05/25 20:00

http://poj.org/problem?id=1364 这题题目比较晦涩难懂,我是直接去看的网上的解释。是道差分约束的题,题目大意是这样:有一个序列S={a1,a2,a3,....,am},现在给出一些不等式

使得ai+a(i+1)+a(i+2)+.......+a(i+ni)>ki或者ai+a(i+1)+a(i+2)+.......+a(i+ni)<k。(注意这里是从ai本身开始后面再加ni个数),让你判断是否所有的不等式都满足条件,满足就输出

lamentable kingdom,不满足就输出successful conspiracy。(注意不要输反了,一开始我就是输反了 ,导致一直在查自己SPFA的错。。。)
由于差分约束只能解决同时大于等于或者同时小于等于的情况,所以我们需要对题给不等式做一些变形。

1).形如 ai ni gt ki 这种形式的 表示ai+a(i+1)+a(i+2)+.......+a(i+ni)>ki ,我们令Si 表示序列前i项的和 ,则前面不等式等价于 :

S(i+ni)-S(i-1)>ki <=> S(i-1)-S(i+ni)<=-ki -1;

2). 对 ai ni lt ki  一样的道理,转化为S(i+ni)-S(i-1)<ki  <=> S(i+ni)-S(i-1)<=ki-1;

这就是所有的通式,最后根据差分约束建立有向图:

gt: 建立有向边:(i+ni) -> (i-1)  权值为:-ki-1

lt :建立有向边: (i-1) -> (i+ni) 权值为:ki-1

最后判断是否所有不等式成立的条件就是是否有负环产生。直接用Bellman_ford或者spfa都行,接下来的就跟poj2983的处理一样了。下面是AC的代码:

再这里抱怨一句,不知道为什么,这题我用添加超源点的方式一直WA,改用下面这种方式才A了,但是把相同的添加源点的代码写到poj2983(http://blog.csdn.net/lyx35405/article/details/10053309)里面竟然能过。。

#include <cstdio>#include <cstring>#include <iostream>#include <queue>#include <algorithm>using namespace std;#define inf 999999999#define maxn 1003*10struct node{    int y,w,next;}edge[maxn];queue<int> que;int n,num,m;int first[maxn],dis[maxn],fnum[maxn];bool visit[maxn];void initGraph(int x,int y,int w){    edge[++num].y=y;edge[num].w=w;    edge[num].next=first[x];    first[x]=num;//相当于链表的头插入法,顶点x的所有边为一个邻接表}bool SPFA(){    memset(visit,1,sizeof(visit));    memset(fnum,0,sizeof(fnum));    memset(dis,0,sizeof(dis));    for(int i=0;i<=n;i++) que.push(i);    //visit[n+1]=1;    while(!que.empty())    {        int x=que.front();        que.pop();        visit[x]=0;        for(int i=first[x];i!=0;i=edge[i].next)        {            int y=edge[i].y;            if(dis[x]+edge[i].w<dis[y])            {                dis[y]=dis[x]+edge[i].w;                if(!visit[y])                {                    visit[y]=1;                    if(++fnum[y]>n) return 0;//无解                    //printf("fnum[%d]=%d\n",y,fnum[y] );                    que.push(y);                }            }        }    }    return 1 ;//有解}int main(){    int si,ni,ki;    char op[5];    while(scanf("%d",&n)==1&&n)    {        scanf("%d",&m);        num=0;        memset(first,0,sizeof(first));        while(m--)        {            scanf("%d%d%s%d",&si,&ni,op,&ki);            if(op[0]=='g')                initGraph(si+ni,si-1,-ki-1);            else                initGraph(si-1,si+ni,ki-1);        }        if(!SPFA()) printf("successful conspiracy\n");        else printf("lamentable kingdom\n");    }       return 0;}


原创粉丝点击