洛谷 P1807 最长路_NOI导刊2010提升(07)题解

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

 

读题,加上了-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;
    
}
56分代码

 

问了问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;
    
}
67分代码

 

继续问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;
    
}
89分代码

 

错在哪里了呢??

再仔细读一遍代码

发现特判-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;
    
}
100分代码
相关文章
相关标签/搜索