poj1534(差分约束+多次spfa使其联通)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1534

题意:

有n个作业,第 i 个作业所需的时间是 time[i],第i个作业开始的时间为d[i],时间从0开始。求满足这些约束条件时,花费时间最小的情况时,每一个作业的开始时间。

四种约束条件如下:
SAS u v 表示 v开始后 u 才能开始;d(u)>=d(v);
SAF u v 表示 v结束后 u 才能开始;d(u)>=d(v)+time[v];
FAF u v 表示 v结束后 u 才能结束;d(u)+time[u]>=d(v)+time[v];
FAS u v 表示 v开始后 u 才能结束;d(u)+time[u]>=d(v);

分析:求最小时间,就是差分约束跑最长路即可。

代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <queue>

using namespace std;
const int maxn =100000+5;
const int inf =0x3f3f3f3f;

int head[maxn],d[maxn],vis[maxn],cnt,N,num[maxn],time[maxn],flag[maxn],k=1;
queue<int> q;

void init()
{
    cnt=0;
    memset(flag,0,sizeof(flag));
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
    while(!q.empty())
        q.pop();
}

struct Edge
{
    int v,w,next;
    Edge() {};
    Edge(int _v, int _w, int _next)
    {
        v=_v, w=_w, next=_next;
    }
} e[20*maxn];

void add_edge(int u, int v, int w)
{
    e[cnt]=Edge(v,w,head[u]);
    head[u]=cnt++;
}

int spfa(int s)
{
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    d[s]=0;
    q.push(s);
    vis[s]=1;
    num[s]++;
    while(!q.empty())
    {
        int u= q.front();
        q.pop();
        vis[u]=0;
        flag[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if(d[v]<d[u]+e[i].w)
            {
                d[v]=d[u]+e[i].w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                    num[v]++;
                    if(num[v]>N)
                        return 0;
                }
            }
        }
    }

    return 1;
}

int main()
{
    while(cin>>N&&N)
    {
        init();
        for(int i=1; i<=N; i++)
            cin>>time[i];
        string str;
        int a,b;
        while(cin>>str&&str!="#")
        {
            cin>>a>>b;
            if(str=="SAS")
            {
                add_edge(b,a,0);
            }
            else if(str=="SAF")
            {
                add_edge(b,a,time[b]);

            }
            else if(str=="FAF")
            {
                add_edge(b,a,time[b]-time[a]);

            }
            else if(str=="FAS")
            {
                add_edge(b,a,-time[a]);
            }
        }
        cout<<"Case "<<k++<<":"<<endl;
        int yes;
        for(int i=1; i<=N; i++)
        {
            if(!flag[i])
            {
                yes=spfa(i);
            }
            if(yes==0)
                break;
        }

        if(yes)
        {
            for(int i=1; i<=N; i++)
            {
                cout<<i<<" "<<d[i]<<endl;
            }
        }
        else
        {
            cout<<"impossible"<<endl;

        }
        cout<<endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36300700/article/details/80807876