题目描述
Farmer John’s N cows (1 <= N <= 10,000) are conveniently numbered 1…N.
Each cow i takes T(i) units of time to milk. Unfortunately, some cows must be milked before others, owing to the layout of FJ’s barn. If cow A must be milked before cow B, then FJ needs to completely finish milking A before he can start milking B.
In order to milk his cows as quickly as possible, FJ has hired a large number of farmhands to help with the task – enough to milk any number of cows at the same time. However, even though cows can be milked at the same time, there is a limit to how quickly the entire process can proceed due to the constraints requiring certain cows to be milked before others. Please help FJ compute the minimum total time the milking process must take.
输入
-
Line 1: Two space-separated integers: N (the number of cows) and M(the number of milking constraints; 1 <= M <= 50,000).
-
Lines 2…1+N: Line i+1 contains the value of T(i) (1 <= T(i) <= 100,000).
-
Lines 2+N…1+N+M: Each line contains two space-separated integers A and B, indicating that cow A must be fully milked before one can start milking cow B. These constraints will never form a cycle, so a solution is always possible.
输出
- Line 1: The minimum amount of time required to milk all cows.
样例输入
3 1
10
5
6
3 2
样例输出
11
提示
INPUT DETAILS:
There are 3 cows. The time required to milk each cow is 10, 5, and 6,respectively. Cow 3 must be fully milked before we can start milking cow 2.
OUTPUT DETAILS:
Cows 1 and 3 can initially be milked at the same time. When cow 3 is finished with milking, cow 2 can then begin. All cows are finished milking after 11 units of time have elapsed.
题意:
一共有n头奶牛,每头奶牛挤奶都会消耗一定的时间
t
i
t_i
ti
然后有
m
m
m个关系,
u
−
v
u-v
u−v,其含义是
u
u
u必须在
v
v
v之前挤奶,而且有足够的人手多线程挤奶,问为这
n
n
n头奶牛挤完奶一共需要消耗多长时间
思路:
首先可以确定这m个关系中,不会出现环的情况,所以说可以考虑用
s
p
f
a
spfa
spfa来处理这道题目,怎么来确定最后被挤奶的奶牛呢?
因为
m
m
m个关系可以看作是有向边,所以最后被挤奶的奶牛一定是出度为0的,但出度为0的点可能并不唯一
怎样来确定从那一头牛开始?
类似的我们可以知道一定是从入读为0的点开始,入度为0的点也可能并不唯一
所以我们可以建立一个超级源点
0
0
0与所有入度为0的点相连,然后让所有出度为0的点与超级汇点
n
+
1
n+1
n+1相连,所以说最终的答案就是从超级源点走到超级汇点的最长路径
因为需要从0转移到其他节点,所以说可以先给0号节点设置一个点权1,最终减去即可
ac_code:
#define Clear(x,val) memset(x,val,sizeof x)
int in[maxn],out[maxn];
typedef pair<ll,int> PII;
int n,m;
vector<int>gra[maxn];
ll a[maxn];
ll dis[maxn];
bool vis[maxn];
int cnt,head[maxn];
void init() {
cnt = 0;
Clear(head,-1);
}
struct node {
int v,nex;
} e[maxn];
void add(int u,int v) {
e[cnt].v = v;
e[cnt].nex = head[u];
head[u] = cnt ++;
}///ac
void spfa() {
dis[0] = 0;
vis[0] = 1;
// queue<PII> que;
priority_queue<PII,vector<PII>,greater<PII> > que;
que.push({0,0});
while(que.size()) {
PII cur = que.top();
que.pop();
int u = cur.second;
vis[u] = false;
for(int i=head[u]; ~i; i=e[i].nex) {
int to = e[i].v;
if(dis[to] < dis[u] + a[u]) {
dis[to] = dis[u] + a[u];
if(!vis[to]) {
vis[to] = true;
que.push({dis[to],to});
}
}
}
}
}
int main() {
n = read,m = read;
init();
a[0] = 1;
Clear(dis,0);
Clear(vis,0);
for(int i=1; i<=n; i++) a[i] = read;
for(int i=1; i<=m; i++) {
int u = read,v = read;
gra[u].push_back(v);
add(u,v);
in[v] ++;
out[u] ++;
}
for(int i=1; i<=n; i++) {
if(!in[i]) add(0,i);
if(!out[i]) add(i,n+1);
}
spfa();
cout << dis[n + 1] - 1 << endl;
return 0;
}