POJ 3553
假设同一时刻t有两个活动i,j可做,
先做i s1 =max(t+pi-di,t+pi+pj-dj,0)
先做j s2 =max(t+pj-dj,t+pi+pj-di,0)
//此处省不省略0对证明不影响只对s1,s2影响。
//举例来说,省略0是超时完成要扣钱,提前完成有奖金
//而不省略0是是超时完成要扣钱,提前完成没有事件发生
1) s1中 t+pi-di>t+pi+pj-dj
s2中 t+pj-dj>t+pi+pj-di
有0>pi+pj,显而不符
2)s1中 t+pi-di>t+pi+pj-dj,即-di>pj-dj ,可推出di<dj-pj<dj
s2中 t+pj-dj<=t+pi+pj-di
s2-s1=pj,显然s1<=s2
3)s1中 t+pi-di<=t+pi+pj-dj,
s2中 t+pj-dj>t+pi+pj-di 即-dj>pi-di ,推出dj<di-pi<di
s2-s1=-pj,显然s2<=s1
4) s1中 t+pi-di<t+pi+pj-dj
s2中 t+pj-dj<t+pi+pj-di
s2-s1=dj-di,结果与(2)(3)相符
因此,假设同一时刻t有两个活动i,j可做,应优先做d值小的(与p无关)
假设同一时刻t有两个活动i,j可做,
先做i s1 =max(t+pi-di,t+pi+pj-dj,0)
先做j s2 =max(t+pj-dj,t+pi+pj-di,0)
//此处省不省略0对证明不影响只对s1,s2影响。
//举例来说,省略0是超时完成要扣钱,提前完成有奖金
//而不省略0是是超时完成要扣钱,提前完成没有事件发生
1) s1中 t+pi-di>t+pi+pj-dj
s2中 t+pj-dj>t+pi+pj-di
有0>pi+pj,显而不符
2)s1中 t+pi-di>t+pi+pj-dj,即-di>pj-dj ,可推出di<dj-pj<dj
s2中 t+pj-dj<=t+pi+pj-di
s2-s1=pj,显然s1<=s2
3)s1中 t+pi-di<=t+pi+pj-dj,
s2中 t+pj-dj>t+pi+pj-di 即-dj>pi-di ,推出dj<di-pi<di
s2-s1=-pj,显然s2<=s1
4) s1中 t+pi-di<t+pi+pj-dj
s2中 t+pj-dj<t+pi+pj-di
s2-s1=dj-di,结果与(2)(3)相符
因此,假设同一时刻t有两个活动i,j可做,应优先做d值小的(与p无关)
拓扑5W个点,还要用上优先队列。
#include<string.h>
#include<stdio.h>
#define N 50005
#define M 500005
struct edge{
int to,next;
}e[M];
int ru[N],head[N],tr[N],d[N],heap[N],fheap[N];
int o,n,m,size;
void swap(int *a,int *b)
{ int swap;
swap=*a;*a=*b;*b=swap;
}
int min(int a,int b)
{ return a>b?b:a;
}
void up(int i)
{ while (i>1)
{ if (d[heap[i]]<d[heap[i>>1]])
{swap(fheap+heap[i>>1],fheap+heap[i]);
swap(heap+(i>>1),heap+i);
}
else break;
i>>=1;
}
}
void down(int i)
{ while (i<<1<=size)
{i<<=1;
if (i<size&&d[heap[i+1]]<d[heap[i]]) i++;
if (d[heap[i]]<d[heap[i>>1]]) {swap(fheap+heap[i>>1],fheap+heap[i]);
swap(heap+(i>>1),heap+i);
}
else break;
}
}
void add(int x,int y)
{ ru[y]++;
e[o].to=y;
e[o].next=head[x];
head[x]=o++;
}
void topu()
{ int sum=0,i,j,yiip;
size=0;
for (i=1;i<=n;i++)
if (ru[i]==0)
{ heap[++size]=i;
fheap[i]=size;
up(size);
}
while (sum<n)
{ i=heap[1];
tr[sum]=i;
for (int k=head[i];k!=-1;k=e[k].next)
{ru[e[k].to]--;
if (ru[e[k].to]==0) {heap[++size]=e[k].to;
fheap[e[k].to]=size;
up(size);
}
}
sum++;
yiip=fheap[i];
fheap[heap[size]]=yiip;
heap[yiip]=heap[size];
size--;
down(yiip);
}
for (i=0;i<n;i++)
printf("%d\n",tr[i]);
}
void doit()
{ int i,j,x,y;
memset(ru,0,sizeof(ru));
memset(head,255,sizeof(head)); o=0;
for (i=1;i<=n;i++)
scanf("%d%d",&d[i],&d[i]);
scanf("%d",&m);
for (i=1;i<=m;i++)
{scanf("%d%d",&x,&y);
add(x,y);
}
topu();
}
int main()
{ while (scanf("%d",&n)!=EOF) doit();
return 0;
}
164

被折叠的 条评论
为什么被折叠?



