至關與一個拓撲排序的模板題吧node
蒟蒻的辛酸史ios
題目大意:給你一個有向無環圖,讓你求出1到n的最長路,若是沒有路徑,就輸出-1ide
思路:一開始覺得是一個很裸的拓撲排序spa
就不看題目,直接打了一遍拓撲排序code
而後就獲得了45分的成績blog
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #define int long long int using namespace std; struct node { int u; int v; int w; int next; }data[1000010]; int head[1000010]; int cnt; int n,m; inline void add(int u,int v,int w) { cnt++; data[cnt].v=v; data[cnt].w=w; data[cnt].next=head[u]; head[u]=cnt; } queue<int> q; int fl[1000010]; int value[1000010]; signed main() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); fl[v]++; } for(int i=1;i<=n;i++) { if(fl[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { if(value[data[i].v]<value[x]+data[i].w) { value[data[i].v]=value[x]+data[i].w; } fl[data[i].v]--; if(!fl[data[i].v]) { q.push(data[i].v); } } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,value[i]); } cout<<ans<<endl; return 0; }
讀題,加上了-1排序
獲得了56分的好成績隊列
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #define int long long int using namespace std; struct node { int u; int v; int w; int next; }data[1000010]; int head[1000010]; int cnt; int n,m; inline void add(int u,int v,int w) { cnt++; data[cnt].v=v; data[cnt].w=w; data[cnt].next=head[u]; head[u]=cnt; } queue<int> q; int fl[1000010]; int value[1000010]; signed main() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); fl[v]++; } for(int i=1;i<=n;i++) { if(fl[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { if(value[data[i].v]<value[x]+data[i].w) { value[data[i].v]=value[x]+data[i].w; } fl[data[i].v]--; if(!fl[data[i].v]) { q.push(data[i].v); } } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,value[i]); } if(ans==0) { cout<<-1<<endl; } else cout<<ans<<endl; return 0; }
問了問lzt大佬ci
他說什麼求的是1到n的最長路,而不是整張圖中的最長路。。string
修改,指望得分100
實際得分:67
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #define int long long int using namespace std; struct node { int u; int v; int w; int next; }data[1000010]; int head[1000010]; int cnt; int n,m; inline void add(int u,int v,int w) { cnt++; data[cnt].v=v; data[cnt].w=w; data[cnt].next=head[u]; head[u]=cnt; } queue<int> q; int fl[1000010]; int value[1000010]; signed main() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); fl[v]++; } for(int i=1;i<=n;i++) { if(fl[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { if(value[data[i].v]<value[x]+data[i].w) { value[data[i].v]=value[x]+data[i].w; } fl[data[i].v]--; if(fl[data[i].v]==0) { q.push(data[i].v); } } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,value[i]); } if(ans==0) { cout<<-1<<endl; } else cout<<value[n]<<endl; return 0; }
繼續問lzt大佬,
說什麼要先刪邊再求
也就是說,在整張圖中,可能存在不少入度爲零的點
此時咱們就須要刪邊(由於求1到n的最長路,和那些不是一的點有什麼關係呢??)
打個比方:若是你不刪邊,也不處理那些入度爲零的點
就比如你想知道你談的戀愛中哪場談的最久,若是不處理,就成了你和你的全部前女朋友中,大家談的全部戀愛中時間最久的那個。
也就是你求你談的最長的一場戀愛,和你前女朋友們談的最長的戀愛不是一個東西
好,那麼咱們先把除了1以外入度爲零的點都放進去
跑一邊拓撲排序,就達到了刪邊的目的
而後再把一放入隊列中,進行第二遍拓撲排序
這時,到達n的最長路就是1到n的最長路
指望得分100
實際得分89..
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #define int long long int using namespace std; struct node { int u; int v; int w; int next; }data[1000010]; int head[1000010]; int cnt; int n,m; inline void add(int u,int v,int w) { cnt++; data[cnt].v=v; data[cnt].w=w; data[cnt].next=head[u]; head[u]=cnt; } queue<int> q; int fl[1000010]; int value[1000010]; signed main() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); fl[v]++; } for(int i=2;i<=n;i++) { if(fl[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { fl[data[i].v]--; if(fl[data[i].v]==0) { q.push(data[i].v); } } } q.push(1); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { if(value[data[i].v]<value[x]+data[i].w) { value[data[i].v]=value[x]+data[i].w; } fl[data[i].v]--; if(fl[data[i].v]==0) { q.push(data[i].v); } } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,value[i]); } if(ans==0) { cout<<-1<<endl; } else cout<<value[n]<<endl; return 0; }
錯在哪裏了呢??
再仔細讀一遍代碼
發現特判-1的地方寫錯了
ans==0是指整張圖中的最長路是零
可是並非說明了1到n之間有路
而後咱們就特判一下,若是value[n]==0
那麼咱們就輸出-1
這是由於,當ans>0時,只是說明了圖中有點相連,並無說明1到n之間有路可走
這時咱們特判一下,當其是零的時候,就說明了沒有路可走,那麼咱們就輸出-1
指望得分100
實際得分100
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #define int long long int using namespace std; struct node { int u; int v; int w; int next; }data[1000010]; int head[1000010]; int cnt; int n,m; inline void add(int u,int v,int w) { cnt++; data[cnt].v=v; data[cnt].w=w; data[cnt].next=head[u]; head[u]=cnt; } queue<int> q; int fl[1000010]; int value[1000010]; signed main() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); fl[v]++; } for(int i=2;i<=n;i++) { if(fl[i]==0) { q.push(i); } } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { fl[data[i].v]--; if(fl[data[i].v]==0) { q.push(data[i].v); } } } q.push(1); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=data[i].next) { if(value[data[i].v]<value[x]+data[i].w) { value[data[i].v]=value[x]+data[i].w; } fl[data[i].v]--; if(fl[data[i].v]==0) { q.push(data[i].v); } } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,value[i]); } if(ans==0||value[n]==0) { cout<<-1<<endl; } else cout<<value[n]<<endl; return 0; }