POJ 3683 Priest John's Busiest Day

POJ_3683

这是一个2-SAT的问题,其实算法以及构图并不难想,但是编码的复杂度比较高。

在构图的时候,我们需要判断两段时间是否相交,比较容易的办法就是if(s1<t2&&t1>s2),其中[s1,t1][s2,t2]为两段时间。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXD 2010
#define MAXM 4000010
int S[MAXD], T[MAXD], D[MAXD], N;
int Gfirst[MAXD], Gnext[MAXM], Gv[MAXM], Ge;
int gfirst[MAXD], gnext[MAXM], gv[MAXM], ge, dg[MAXD][MAXD], del[MAXD];
int dfn[MAXD], color[MAXD], low[MAXD], cnt, col;
int ins[MAXD], s[MAXD], top, group[MAXD][MAXD], num[MAXD];
int topo[MAXD], vis[MAXD], t, ans[MAXD], res;
int cmp(const void * _p,const void * _q)
{
int *p = (int *)_p;
int *q = (int *)_q;
return *p - *q;
}
void add_G(int i, int j)
{
Gv[Ge] = j;
Gnext[Ge] = Gfirst[i];
Gfirst[i] = Ge;
Ge ++;
}
void add_g(int i, int j)
{
gv[ge] = j;
gnext[ge] = gfirst[i];
gfirst[i] = ge;
ge ++;
}
void init()
{
int i, j, a, b;
char str[10];
for(i = 0; i < N; i ++)
{
scanf("%s", str);
sscanf(str, "%d:%d", &a, &b);
S[i] = a * 60 + b;
scanf("%s", str);
sscanf(str, "%d:%d", &a, &b);
T[i] = a * 60 + b;
scanf("%d", &D[i]);
}
Ge = 0;
memset(Gfirst, -1, sizeof(Gfirst));
for(i = 0; i < N; i ++)
{
int si0 = S[i], si1 = T[i] - D[i], ti0 = S[i] + D[i], ti1 = T[i];
for(j = i + 1; j < N; j ++)
{
int sj0 = S[j], sj1 = T[j] - D[j], tj0 = S[j] + D[j], tj1 = T[j];
if(si0 < tj0 && ti0 > sj0)
{
add_G(2 * i, 2 * j + 1);
add_G(2 * j, 2 * i + 1);
}
if(si0 < tj1 && ti0 > sj1)
{
add_G(2 * i, 2 * j);
add_G(2 * j + 1, 2 * i + 1);
}
if(si1 < tj0 && ti1 > sj0)
{
add_G(2 * i + 1, 2 * j + 1);
add_G(2 * j, 2 * i);
}
if(si1 < tj1 && ti1 > sj1)
{
add_G(2 * i + 1, 2 * j);
add_G(2 * j + 1, 2 * i);
}
}
}
}
void tarjan(int u)
{
int i, e;
dfn[u] = low[u] = ++ cnt;
for(e = Gfirst[u]; e != -1; e = Gnext[e])
{
if(!dfn[Gv[e]])
{
s[top ++] = Gv[e];
ins[Gv[e]] = 1;
tarjan(Gv[e]);
if(low[Gv[e]] < low[u])
low[u] = low[Gv[e]];
}
else if(ins[Gv[e]] && dfn[Gv[e]] < low[u])
low[u] = dfn[Gv[e]];
}
if(low[u] == dfn[u])
{
for(i = 0, s[top] = -1; s[top] != u; i ++)
{
top --;
ins[s[top]] = 0;
color[s[top]] = col;
group[col][i] = s[top];
}
num[col] = i;
col ++;
}
}
void dfs(int u)
{
int e;
vis[u] = 1;
for(e = gfirst[u]; e != -1; e = gnext[e])
if(!vis[gv[e]])
dfs(gv[e]);
topo[-- t] = u;
}
void toposort()
{
int i;
t = col;
memset(vis , 0, sizeof(vis));
for(i = 0; i < col; i ++)
if(!vis[i])
dfs(i);
}
void del_g(int u)
{
int e;
del[u] = 1;
for(e = gfirst[u]; e != -1; e = gnext[e])
if(!del[gv[e]])
del_g(gv[e]);
}
int com()
{
int i, j, e;
cnt = top = col = 0;
memset(dfn, 0, sizeof(dfn));
memset(ins, 0, sizeof(ins));
for(i = 0; i < 2 * N; i ++)
if(!dfn[i])
{
s[top ++] = i;
ins[i] = 1;
tarjan(i);
}
for(i = 0; i < 2 * N; i ++)
{
if(color[i] == color[i ^ 1])
return 0;
}
ge = 0;
memset(gfirst, -1, sizeof(gfirst));
memset(dg, 0, sizeof(dg));
for(i = 0; i < 2 * N; i ++)
for(e = Gfirst[i]; e != -1; e = Gnext[e])
if(color[i] != color[Gv[e]] && !dg[color[Gv[e]]][color[i]])
{
dg[color[Gv[e]]][color[i]] = 1;
add_g(color[Gv[e]], color[i]);
}
toposort();
memset(del, 0, sizeof(del));
res = 0;
for(i = 0; i < col; i ++)
if(!del[topo[i]])
{
del[topo[i]] = 1;
for(j = 0; j < num[topo[i]]; j ++)
{
int p = group[topo[i]][j];
ans[res ++] = p;
if(!del[color[p ^ 1]])
del_g(color[p ^ 1]);
}
}
return 1;
}
void printpath()
{
int i;
qsort(ans, res, sizeof(ans[0]), cmp);
for(i = 0; i < res; i ++)
{
int p = ans[i] / 2;
if(ans[i]%2 == 0)
{
printf("%02d:%02d ", S[p] / 60, S[p] % 60);
printf("%02d:%02d\n", (S[p] + D[p]) / 60, (S[p] + D[p]) % 60);
}
else
{
printf("%02d:%02d ", (T[p] - D[p]) / 60, (T[p] - D[p]) % 60);
printf("%02d:%02d\n", T[p] / 60, T[p] % 60);
}
}
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
if(com())
{
printf("YES\n");
printpath();
}
else
printf("NO\n");
}
return 0;
}


你可能感兴趣的:(poj)