洛谷 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分代碼
相關文章
相關標籤/搜索