zoukankan      html  css  js  c++  java
  • poj 1364 King(线性差分约束+超级源点+spfa判负环)

    King
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 14791   Accepted: 5226

    Description

    Once, in one kingdom, there was a queen and that queen was expecting a baby. The queen prayed: ``If my child was a son and if only he was a sound king.'' After nine months her child was born, and indeed, she gave birth to a nice son.
    Unfortunately, as it used to happen in royal families, the son was a little retarded. After many years of study he was able just to add integer numbers and to compare whether the result is greater or less than a given integer number. In addition, the numbers had to be written in a sequence and he was able to sum just continuous subsequences of the sequence.

    The old king was very unhappy of his son. But he was ready to make everything to enable his son to govern the kingdom after his death. With regards to his son's skills he decided that every problem the king had to decide about had to be presented in a form of a finite sequence of integer numbers and the decision about it would be done by stating an integer constraint (i.e. an upper or lower limit) for the sum of that sequence. In this way there was at least some hope that his son would be able to make some decisions.

    After the old king died, the young king began to reign. But very soon, a lot of people became very unsatisfied with his decisions and decided to dethrone him. They tried to do it by proving that his decisions were wrong.

    Therefore some conspirators presented to the young king a set of problems that he had to decide about. The set of problems was in the form of subsequences Si = {aSi, aSi+1, ..., aSi+ni} of a sequence S = {a1, a2, ..., an}. The king thought a minute and then decided, i.e. he set for the sum aSi + aSi+1 + ... + aSi+ni of each subsequence Si an integer constraint ki (i.e. aSi + aSi+1 + ... + aSi+ni < ki or aSi + aSi+1 + ... + aSi+ni > ki resp.) and declared these constraints as his decisions.

    After a while he realized that some of his decisions were wrong. He could not revoke the declared constraints but trying to save himself he decided to fake the sequence that he was given. He ordered to his advisors to find such a sequence S that would satisfy the constraints he set. Help the advisors of the king and write a program that decides whether such a sequence exists or not.

    Input

    The input consists of blocks of lines. Each block except the last corresponds to one set of problems and king's decisions about them. In the first line of the block there are integers n, and m where 0 < n <= 100 is length of the sequence S and 0 < m <= 100 is the number of subsequences Si. Next m lines contain particular decisions coded in the form of quadruples si, ni, oi, ki, where oi represents operator > (coded as gt) or operator < (coded as lt) respectively. The symbols si, ni and ki have the meaning described above. The last block consists of just one line containing 0.

    Output

    The output contains the lines corresponding to the blocks in the input. A line contains text successful conspiracy when such a sequence does not exist. Otherwise it contains text lamentable kingdom. There is no line in the output corresponding to the last ``null'' block of the input.

    Sample Input

    4 2
    1 2 gt 0
    2 2 lt 2
    1 2
    1 0 gt 0
    1 0 lt 0
    0

    Sample Output

    lamentable kingdom
    successful conspiracy

    Source

    题目意思:
    问你是否存在一个序列S{a1,a2,a3.....an}
    可以满足下面两种不同数量的约束
    假设s[x]表示a1+....+ax的和
    约束1:x y gt w 比如1 2 gt w
    从a1开始累加,再加2个的和大于w
    根据题目意思即a1+a2+a3>w
    变形一下即s[3]-s[0]>w
    移动位置变形一下:s[0]-s[3]<-w
    继续变形:s[0]-s[3]<=-w-1
    即通式为:s[x-1]-s[x+y]<=-w-1
    约束2:x y lt w 比如2 2 lt w
    从a2开始累加,再加两个的和小于w
    即a2+a3+a4<w
    变形一下:s[4]-s[1]<w
    继续变形:s[4]-s[1]<=w-1
    通式:s[x+y]-s[x-1]<=w-1
    都是形如x[i]-x[j]<=c的形式
    从j指向i 权值为c这样建图
    注意:建图完毕之后存在n+1个点,然后在加一个超级源点s,让s到这n+1个点的距离都为0
    这样是为了保证图的连通性
    然后判断一下图中是否存在负环,存在负环则表示某些约束不能满足
    则不存在这样的序列
    加了超级源点之后图中一共有n+2个点!!!
    建议spfa判负环
     
    code:
    #include<stdio.h>
    #include<iostream>
    #include<math.h>
    #include<string.h>
    #include<set>
    #include<map>
    #include<list>
    #include<math.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define INF 9999999999
    #define me(a,x) memset(a,x,sizeof(a))
    int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
    int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
    
    int getval()
    {
        int ret(0);
        char c;
        while((c=getchar())==' '||c=='
    '||c=='
    ');
        ret=c-'0';
        while((c=getchar())!=' '&&c!='
    '&&c!='
    ')
            ret=ret*10+c-'0';
        return ret;
    }
    void out(int a)
    {
        if(a>9)
            out(a/10);
        putchar(a%10+'0');
    }
    
    #define max_v 1005
    struct node
    {
        int v;
        LL w;
        node(int vv=0,LL ww=0):v(vv),w(ww) {}
    };
    LL dis[max_v];
    int vis[max_v];
    int cnt[max_v];
    vector<node> G[max_v];
    queue<int> q;
    
    void init()
    {
        for(int i=0; i<max_v; i++)
        {
            G[i].clear();
            dis[i]=INF;
            vis[i]=0;
            cnt[i]=0;
        }
        while(!q.empty())
            q.pop();
    }
    
    int spfa(int s,int n)
    {
        vis[s]=1;
        dis[s]=0;
        q.push(s);
        cnt[s]++;
    
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
    
            for(int j=0; j<G[u].size(); j++)
            {
                int v=G[u][j].v;
                LL w=G[u][j].w;
    
                if(dis[v]>dis[u]+w)
                {
                    dis[v]=dis[u]+w;
                    if(vis[v]==0)
                    {
                        q.push(v);
                        cnt[v]++;
                        vis[v]=1;
    
                        if(cnt[v]>n)
                            return 0;
                    }
                }
            }
        }
        return 1;
    }
    int f(int u,int v)
    {
        for(int j=0; j<G[u].size(); j++)
        {
            if(G[u][j].v==v)
                return 0;
        }
        return 1;
    }
    int main()
    {
        int n,m;
        char str[10];
        int x,y,w;
        while(~scanf("%d",&n))
        {
            if(n==0)
                break;
            scanf("%d",&m);
            init();
            while(m--)
            {
                scanf("%d %d %s %d",&x,&y,str,&w);
                if(strcmp(str,"gt")==0)
                {
                    int u=x+y;
                    int v=x-1;
                    if(f(u,v))
                        G[u].push_back(node(v,-w-1));
                }else if(strcmp(str,"lt")==0)
                {
                    int u=x+y;
                    int v=x-1;
                    if(f(v,u))
                        G[v].push_back(node(u,w-1));
                }
            }
            int s=n+1;//超级源点 保证图的连通性
            for(int i=0;i<=n;i++)//超级源点到每个点的距离为0
            {
                if(f(s,i))
                    G[s].push_back(node(i,0));
            }
            int flag=spfa(s,n+2);
            if(flag==1)
                printf("lamentable kingdom
    ");
            else
                printf("successful conspiracy
    ");
        }
        return 0;
    }
    /*
    题目意思:
    问你是否存在一个序列S{a1,a2,a3.....an}
    可以满足下面两种不同数量的约束
    
    假设s[x]表示a1+....+ax的和
    
    约束1:x y gt w 比如1 2 gt w
    从a1开始累加,再加2个的和大于w
    根据题目意思即a1+a2+a3>w
    变形一下即s[3]-s[0]>w
    移动位置变形一下:s[0]-s[3]<-w
    继续变形:s[0]-s[3]<=-w-1
    即通式为:s[x-1]-s[x+y]<=-w-1
    
    约束2:x y lt w 比如2 2 lt w
    从a2开始累加,再加两个的和小于w
    即a2+a3+a4<w
    变形一下:s[4]-s[1]<w
    继续变形:s[4]-s[1]<=w-1
    通式:s[x+y]-s[x-1]<=w-1
    
    都是形如x[i]-x[j]<=c的形式
    从j指向i 权值为c这样建图
    
    注意:建图完毕之后存在n+1个点,然后在加一个超级源点s,让s到这n+1个点的距离都为0
    这样是为了保证图的连通性
    然后判断一下图中是否存在负环,存在负环则表示某些约束不能满足
    则不存在这样的序列
    
    加了超级源点之后图中一共有n+2个点!!!
    
    建议spfa判负环
    */
    心之所向,素履以往
  • 相关阅读:
    day36 08-Hibernate抓取策略:批量抓取
    day36 07-Hibernate抓取策略:many-to-one上的抓取策略
    day36 06-Hibernate抓取策略:set集合上的抓取策略
    day36 05-Hibernate检索方式:离线条件查询
    day36 04-Hibernate检索方式:多表连接查询
    day36 03-Hibernate检索方式:排序、参数绑定、投影查询
    【收集】11款Linux数据恢复工具
    【收集】11款Linux数据恢复工具
    7个免费的Linux FTP客户端工具
    7个免费的Linux FTP客户端工具
  • 原文地址:https://www.cnblogs.com/yinbiao/p/10003995.html
Copyright © 2011-2022 走看看