题目来源:HDU 1534 Schedule Problem
题意:若干个派对 每个派对需要连续几天的时间 接下来有一些限制条件 诸如第i个派对开始时间必须在第j个派对开始之后..(4种)
求出任意一种安排的方案 无解输出impossible
思路:差分约束求最长路求最小值的类型
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 10010;
const int INF = -999999999;
struct edge
{
int v, w;
};
vector <edge> G[maxn];
bool inq[maxn];
int d[maxn];
int cnt[maxn];
int a[maxn];
int n, s, e;
bool SPFA()
{
memset(inq, false, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i <= n; i++)
d[i] = INF;
d[0] = 0;
queue <int> Q;
Q.push(0);
inq[0] = true;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
inq[u] = false;
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i].v;
int w = G[u][i].w;
if(d[v] < d[u] + w)
{
d[v] = d[u] + w;
if(!inq[v])
{
inq[v] = true;
Q.push(v);
if(++cnt[v] > n)
return false;
}
}
}
}
return true;
}
int main()
{
int cas = 1;
while(scanf("%d", &n) && n)
{
for(int i = 0; i <= n; i++)
G[i].clear();
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
char s[100];
while(scanf("%s", s) && s[0] != '#')
{
int u, v;
scanf("%d %d", &u, &v);
if(strcmp(s, "FAS") == 0)//d[u] + a[u] >= d[v]
G[v].push_back((edge){u, -a[u]});
else if(strcmp(s, "FAF") == 0)//d[u] + a[u] >= d[v] + a[v]
G[v].push_back((edge){u, a[v]-a[u]});
else if(strcmp(s, "SAF") == 0)//d[u] >= d[v] + a[v]
G[v].push_back((edge){u, a[v]});
else if(strcmp(s, "SAS") == 0)//d[u] >= d[v]
G[v].push_back((edge){u, 0});
}
for(int i = 1; i <= n; i++)
G[0].push_back((edge){i, 0});
printf("Case %d:\n", cas++);
if(SPFA())
{
for(int i = 1; i <= n; i++)
printf("%d %d\n", i, d[i]);
}
else
{
puts("impossible");
}
puts("");
}
return 0;
}