至关与一个拓扑排序的模板题吧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; }