题意:每一个任务都可以被分成很多部分 然后它们之间一定的关系 需要判断出各个部分最短的开始时间
解法:
SAS u v 表示 v开始后 u 才能开始;f(u)>=f(v);
SAF u v 表示 v结束后 u 才能开始;f(u)>=f(v)+a[v];
FAF u v 表示 v结束后 u 才能结束;f(u)+a[u]>=f(v)+a[v];
FAS u v 表示 v开始后 u 才能结束;f(u)+a[u]>=f(v);
最后还有f[i]>=f[0]
#include<queue>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 55555
#define inf 0x3f3f3f3f
struct edge{
int v,w,next;
edge(int v,int w,int next):v(v),w(w),next(next){}
edge(){}
}e[1111111];
int st,en,n;
int dis[maxn],vis[maxn],head[maxn],a[maxn],in[maxn];
int cnt=0;
void init(){
cnt=0;
st=0;en=n;
memset(head,-1,sizeof head);
}
void add(int u,int v,int w){
e[cnt]=edge(v,w,head[u]);
head[u]=cnt++;
}
int spfa()
{
for(int i=st;i<=en;++i)in[i]=0,vis[i]=0,dis[i]=-inf;
queue<int>q;
q.push(st);
dis[st]=0;vis[st]=1;
int u,v;
while(!q.empty())
{
u=q.front();q.pop();vis[u]=0;
if(++in[u]>n)return 0;
for(int i=head[u];i!=-1;i=e[i].next){
v=e[i].v;
if(dis[v]<dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
return 1;
}
//最小值:x-y>=k y->x w:k
int main()
{
char ss[111];
int u,v,z=1;
while(~scanf("%d",&n),n){
init();
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
while(scanf("%s",ss)){
if(strcmp(ss,"#")==0)break;
scanf("%d%d",&u,&v);
if(strcmp(ss,"SAS")==0)add(v,u,0);
else if(strcmp(ss,"SAF")==0)add(v,u,a[v]);
else if(strcmp(ss,"FAF")==0)add(v,u,a[v]-a[u]);
else add(v,u,-a[u]);
//SAS u v 表示 v开始后 u 才能开始;f(u)>=f(v);
//SAF u v 表示 v结束后 u 才能开始;f(u)>=f(v)+a[v];
//FAF u v 表示 v结束后 u 才能结束;f(u)+a[u]>=f(v)+a[v];
//FAS u v 表示 v开始后 u 才能结束;f(u)+a[u]>=f(v);
}
printf("Case %d:\n",z++);
for(int i=1;i<=n;++i)add(0,i,0);//f[i]>=f[0]
if(spfa()){
for(int i=1;i<=n;++i)printf("%d %d\n",i,dis[i]);
}
else printf("impossible\n");
printf("\n");
}
return 0;
}