壕壕的寒假作业
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);
}
}