【GDKOI2014】壕壕的寒假作业

壕壕的寒假作业

Description

Input

Output
输出n行。第i行输出两个整数,分别表示第i份作业最早完成的时刻以及最晚完成的时刻,两个整数之间以一个空格间隔。

Sample Input
4 4

3 4 5 6

1 2

1 3

2 4

3 4

Sample Output
3 3

7 12

8 12

18 18

Data Constraint
对于30%的数据,n<=100,m<=5000

对于100%的数据,1<=n<=2000,0<=m<=10000,1<=timei<=1000000,1<=ai,bi<=n。

解题思路

求最快什么时候做完作业?
如果要最快完成第(i)份作业,那么是(i)的前继那些作业都要完成之后才能够完成(i),所以,为了尽快完成(i),我们要把(i)的前继的作业全部先做完。
最慢什么时候做完作业?
也就是说再不完成i的前提下,我最多能够做多少作业。那哪些作业是不可以做呢?其实就是它的后继。

那么你先正着做一次(DFS),再反一次做(DFS)就可以了。

Code

#include<cstdio>
#include<cstring>
using namespace std;
int h[20005],a[20005],tot = 0,sum = 0,ans = 0,n,m,vis[2005];

struct edge{
	int to,nxt,z;
}e[20005];
void add(int x,int y,int z)
{
	e[++tot] = (edge){y,h[x],z};
	h[x] = tot;
}
void dfs(int u,int flag)
{
	for (int i = h[u]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (vis[v]) continue;
		if (e[i].z != flag) continue;
		ans += a[v];
		vis[v] = 1;
		dfs(v,flag);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i = 1; i <= n; i++) scanf("%d",&a[i]),sum += a[i];
	for (int i = 1; i <= m; i++)
	{
		int q,p;
		scanf("%d%d",&q,&p);
		add(q,p,1),add(p,q,-1);
	}
	for (int i = 1; i <= n; i++)
	{
		ans = 0;
		memset(vis,0,sizeof(vis));
		vis[i] = 1; 
		dfs(i,-1);
		printf("%d ",ans + a[i]);
		ans = 0;
		memset(vis,0,sizeof(vis));
		vis[i] = 1;
		dfs(i,1);
		printf("%d
",sum - ans);
	}
}
原文地址:https://www.cnblogs.com/nibabadeboke/p/13498582.html