此題困擾本宮甚久。(還不是太菜。)ios
咳咳,再說一下題意啊。。。git
有n個任務,要完成每一個任務都須要一個相應的時間,spa
而有的任務在完成以前必需要完成它對應的準備任務。blog
問完成全部的任務最少須要多少時間?get
搜到一份代碼emm,長這樣,string
雖然短小精悍,,但仍是沒看懂。it
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; int n,i,t,x,ans; int a[10002]; int main() { scanf("%d",&n); while(n--) { scanf("%d%d",&i,&t); while(scanf("%d",&x)&&x!=0) a[i]=max(a[i],a[x]); a[i]+=t; ans=max(ans,a[i]); } printf("%d",ans); return 0; }
而後,爲何呢?io
咱們考慮,每一個任務要想開始的話,就必需要完成他全部的準備任務,class
那麼這個任務開始的時間就是他全部的準備任務中最晚結束的時間;stream
而後這個時間再加上作這個任務自己須要的時間,就是這個任務結束的時間了。
而後任務結束最晚的就是咱們要的答案了。
這樣看來思路好像很清晰,,,,代碼也很明白。。。
那我當時是怎麼不明白的。。。暈。
聽說skr很明顯的拓撲題,每一個點只有入度爲0的時候才能夠入隊。
上個圖吧,源自whymhe。。
解釋一下:
這個點(任務)被訪問,必需要在他前面的點(他的全部準備任務)全被訪問以後,
而後要在它前面的點的結束時間中取個最大值,就是這個任務的開始時間……
(同上同上)
1的結束時間:5
2的結束時間:1+5=6
4的結束時間:5+6=11
3的結束時間:6+3=8
5的結束時間:11(最大的)+1=12
6的結束時間:11(max)+8=19
7結束的時間:19(3,5,6中的max)+4=23
因此拓撲代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; typedef long long LL; inline int read() { char c=getchar(); int num=0; for(; !isdigit(c); c=getchar()); for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num; } const int N=1e4+5; const int INF=1<<30; int n; int rudu[N]; int f[N],g[N]; int ans; int head[N],num_edge; struct Edge { int v,nxt; } edge[N*1005]; inline void add_edge(int u,int v) { edge[++num_edge].v=v; edge[num_edge].nxt=head[u]; head[u]=num_edge; } queue<int> que; void topsort() { for(int i=1; i<=n; ++i) if(rudu[i]==0) que.push(i); int now; while(!que.empty()) { now=que.front(),que.pop(); f[now]+=g[now]; if(head[now]==0) ans=max(ans,f[now]); for(int i=head[now],v; i; i=edge[i].nxt) { v=edge[i].v; --rudu[v]; if(rudu[v]==0) que.push(v); g[v]=max(g[v],f[now]); } } } int main() { n=read(); for(int i=1,a,b; i<=n; ++i) { a=read(),f[a]=read(); while(scanf("%d",&b)&&b) { add_edge(b,a); ++rudu[a]; } } topsort(); cout<<ans; return 0; }
若是你不開心,那我就把右邊這個帥傻子分享給你吧,
你看,他這麼好看,那麼深情的望着你,你還傷心嗎?
真的!這照片盯上他五秒鐘就想笑了。
一切都會過去的。