首页 > 其他分享 >hdu 1534(差分约束)

hdu 1534(差分约束)

时间:2023-05-29 22:32:46浏览次数:47  
标签:hdu .. int head ecnt 1534 MAXN 差分 include


题意:

安排计划,有4种约束方式,给出你这些时间的n个约束..

  如果计划是可行的,求出每一件事发生的最早时间..否则输出“impossible”..

  

  ①. FAF a b a要在b完成后完成..

  ②. FAS a b a要在b开始前完成..

  ③. SAS a b a要在b开始前开始..

  ④. SAF a b a要在b结束前开始..


解题思路:由于每个点之间具有约束关系,可采用差分约束

SAS u,v  S[u]>=S[v];
SAF u,v  S[u]>=S[v]+D[v];
FAF u,v  S[u]+D[u]>=S[v]+D[v];
FAS u,v  S[u]+D[u]>=S[v];


AC:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define INF 1e8
#define MAXN 10005
using namespace std;

struct edge
{
    int u,v,w,next;
}E[200000];
int head[MAXN],ecnt,N,cas;
int dis[MAXN],D[MAXN],cnt[MAXN];
bool vis[MAXN];
queue<int>Q;

void Insert(int u,int v,int w)
{
    E[ecnt].u=u;
    E[ecnt].v=v;
    E[ecnt].w=w;
    E[ecnt].next=head[u];
    head[u]=ecnt++;
}

void Init()
{
    int i,u,v,w;
    char s[20];
    memset(head,-1,sizeof(head)); 
	ecnt=0;
    for(i=1;i<=N;i++)
        scanf("%d",&D[i]);
    while(scanf("%s",s)!=EOF)//建图
    {
        if(s[0]=='#') break;
        scanf("%d%d",&u,&v);
        if(strcmp(s,"SAS")==0)
            Insert(v,u,0);
        else if(strcmp(s,"SAF")==0)
            Insert(v,u,D[v]);
        else if(strcmp(s,"FAF")==0)
            Insert(v,u,D[v]-D[u]);
        else
            Insert(v,u,-D[u]);
    }
    for(i=1;i<=N;i++)//保证每个点都被扩展到
        Insert(0,i,0);
}

bool SPFA()
{
    int i,u,v,w;
    while(!Q.empty()) Q.pop();
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    for(i=0;i<=N;i++)
        dis[i]=-INF;
    Q.push(0);
    dis[0]=0;
    vis[0]=true;
    while(!Q.empty())
    {
        u=Q.front();Q.pop();
        vis[u]=false;
        cnt[u]++;
        if(cnt[u]>N) return false;
        for(i=head[u];i!=-1;i=E[i].next)
        {
            v=E[i].v;w=E[i].w;
            if(dis[v]<dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    Q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
    return true;
}

void Solve()
{
    int i;
    printf("Case %d:\n",cas++);
    if(!SPFA())
        printf("impossible\n");
    else
    {
        for(i=1;i<=N;i++)
            printf("%d %d\n",i,dis[i]);
    }
    printf("\n");
}

int main()
{
    cas=1;
    while(scanf("%d",&N),N)
    {
        Init();
        Solve();
    }
	return 0;
}





标签:hdu,..,int,head,ecnt,1534,MAXN,差分,include
From: https://blog.51cto.com/u_16143128/6374341

相关文章

  • hdu 1532(最大流)
    解题思路:这是一道典型的模板题,直接套用EK算法即可。。。我感觉最大流的本质就是能否找到一个从源点到汇点的增广路径,并将其最小的边作为增加值,沿着增广路上的边进行更新。AC:#include<iostream>#include<cstdio>#include<cstring>#include<queue>usingnamespacestd;consti......
  • hdu 5074(简单dp)
    HatsuneMikuTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:262144/262144K(Java/Others)ProblemDescriptionHatsuneMikuisapopularvirtualsinger.ItisverypopularinbothJapanandChina.Basicallyitisacomputersoftwarethata......
  • hdu 3303(线段树+抽屉原理)
    解题思路:这题利用了抽屉原理,即1-M之间的所有数与M+1的模都不相同。那么可以利用它将要查找所有区间分成[1,Y-1],[Y,2*Y-1],[2*Y,3*Y-1].........一直下去,直到所有的区间都被找一遍,然后就是保存最小的模即可。。。这样就肯定要找每个区间的最小的模,实际上这里可以利用线段树去找,只需......
  • hdu 4417(树状数组+离线算法)
    解题思路:这道题要求某区间内比h小的个数,其实这里可以类似于树状数组求逆序数那样。关键是如何转换成树状数组的模型,这才是本题的难点。我们首先分析,如果知道h在该区间的哪个位置,那么剩下的就很好做了。我们还可以发现,如果找到了当前的比h小的所有点(大于的点我们先忽略掉),那么我们就......
  • hdu 3681(bfs+dfs+状态压缩)
    解题思路:这道题属于图上来回走的问题,可以把重复走的过程弱化,即只强调从u->v的结果,中间经过的节点都不考虑。这道题里面'G','F','Y'是重要的节点,其余的点我们是可以忽略的,也就是说,假设从u->v,我们只需要知道最短路径是多少就可以了,至于是怎么走的,中间绕过了多少个'D'都不是我们关心的......
  • hdu 4012(bfs+位压缩)
    思路:每次涂色以后必有一个格子的颜色是最终的颜色,否则这次涂色根本没意义,所以我们把每次涂色后哪些格子成为最终颜色的所有可能都入队,入队的元素是一个struct包含步数和最终颜色已确定的木块集合,这个集合必须用整数表示,所以用到状态压缩,因为最多只有16个格子,所以用16位的二进制来表......
  • hdu 1593(数学)
    往相反的方面跑,但是,最理想的初始位置并不是圆点和圆上的某一点,应该还有更理想的初始逃跑状态.这里有一点需要注意,就是逃跑者极力想达到理想逃跑初态,而追赶者极力阻止逃跑者达到这一状态,所以,理想初态应该是无论追赶者如何阻止,逃跑者仍然可以达到的理想状态.最理想的......
  • hdu 3577(线段树区间更新)
    题意:输入一个t,表示有t组测试数据;         接下来一行,输入两个数,k,m,其中k表示这个辆车最多可以坐这么多人,m表示有m次询问能否上车;         每一次询问,输入两个数a,b,表示该乘客能否在a站台上车,b站台下车,乘车区间为(a,b--),先后次序;         即我每次询......
  • hdu 3172(并查集+hash)
    解题思路:典型的并查集,只是每个人的名字要转换成数字,可以用map,也可以用字典树,我最开始用的字典树结果爆内存了。。爆内存:#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintmaxn=200000;intn,fa[maxn],trie[maxn][52],cnt,id[2000000],nu......
  • hdu 2795(线段树)
    解题思路:这道题很难想到是用线段树,确实转化的很巧妙实际上,我们只需要利用线段树(记录1-h)维护哪个位置的剩余空间最大即可,即1,2,......,h是线段树的叶子节点,我们每次要找的就是叶子节点的剩余空间的最大值,只要能够想到这里就很容易啦。。另外如果h>n的话,就令h=n,否则就是类似于位置多......