计蒜客暑假集训第一阶段第5场 c题

John loves winter. Every skiing season he goes heli-skiing with his friends. To do so, they rent a helicopter that flies them directly to any mountain in the Alps. From there they follow the picturesque slopes through the untouched snow.

Of course they want to ski on only the best snow, in the best weather they can get. For this they use a combined condition measure and for any given day, they rate all the available slopes.

Can you help them find the most awesome route?

Input Format

The input consists of:

  • one line with two integers nn (2 \le n \le 1000)(2≤n≤1000) and mm (1 \le m \le 5000)(1≤m≤5000),where nn is the number of (11-indexed) connecting points between slopes and mm is the number of slopes.
  • mm lines, each with three integers ss,tt,cc (1 \le s,t \le n, 1 \le c \le 100)(1≤s,t≤n,1≤c≤100) representing a slopefrom point ss to point tt with condition measure cc.

Points without incoming slopes are mountain tops with beautiful scenery, points without outgoing slopes are valleys. The helicopter can land on every connecting point, so the friends can start and end their tour at any point they want. All slopes go downhill, so regardless of where they start, they cannot reach the same point again after taking any of the slopes.

Output Format

Output a single number nn that is the maximum sum of condition measures along a path that the friends could take

Hint

样例输入1

5 5
1 2 15
2 3 12
1 4 17
4 2 11
5 4 9

样例输出1

40

样例输入2

6 6
1 2 2
4 5 2
2 3 3
1 3 2
5 6 2
1 2 4

样例输出2

7

题目大意:

给你一个图,让你求出该图中最长的路径,并输出最长路径的长度。

解题思路:

思路一:每次以入度为0的点为起点进行记忆化搜索,正确。

思路二:运用floyd算法求出最长路,这个地方需要变化一下代码,超时。

思路三:运用bellman算法的队列优化求出最长路,超时。

思路四:运用邻接表储存给的图,然后直接深搜,超时。

代码:

记忆化搜索思路:

#include<bits/stdc++.h>
using namespace std;
int e[1010][1010];//邻接矩阵
int n,m;
int u,v,w;
int visited[1010];//标记数组   如果以i顶点为起点的最长路径已经求出,那么visited[i]等于1
int dp[1010];//储存以i顶点为起点的最长路径的结果
int enter[1010];//标记入度为0的顶点
int ans=-1;
int dfs(int s)//dfs函数返回的是以s顶点为起点的最长路径的值
{
    if(visited[s])//如果这个条件满足,说明以s顶点为起点的最长路径已经求出来了,存储在dp[s]中
        return dp[s];
    for(int i=1;i<=n;i++)//依次访问s顶点的出边点
    {
        if(e[s][i]!=-1)//i顶点是s顶点的出边点
            dp[s]=max(dp[s],dfs(i)+e[s][i]);//如果求以s顶点为起点的最长路径,需要求以i顶点为起点的最长路径,然后加上e[s][i]
    }
    visited[s]=1;//以s顶点为起点的最长路径求完了,标记一下,以后用到的时候直接返回dp[s]就行
    return dp[s];//最后返回dp[s]
}
int main()
{
    cin>>n>>m;
    memset(e,-1,sizeof(e));
    for(int i=0;i<m;i++)
    {
        cin>>u>>v>>w;
        if(e[u][v]==-1)//注意,这个地方,输入的时候有可能输入多次重复边,但是边的权值不一样,我们取最大的权值
            e[u][v]=w;
        else
            e[u][v]=max(e[u][v],w);
        enter[v]=1;//v顶点有入度了
    }
    for(int i=1;i<=n;i++)
    {
        if(!enter[i])//我们用没有入度的顶点作为起始点,因为有入度的顶点如果作为起点,那么加上该顶点的入度边后,最长路径肯定变长
            ans=max(ans,dfs(i));
    }
    cout<<ans<<endl;
}

floyd算法思路:

#include<bits/stdc++.h>
using namespace std;
int e[1010][1010];
int n,m;
int u,v,w;
int maxz=-1;
void floyd()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                if(e[j][k]<(e[j][i]+e[i][k])&&(e[j][i]!=0)&&(e[i][k]!=0))
                {
                    e[j][k]=e[j][i]+e[i][k];
                    maxz=max(maxz,e[j][k]);
                }
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v>>w;
        e[u][v]=w;
    }
    floyd();
    cout<<maxz<<endl;
}

bellman算法思路:

#include<bits/stdc++.h>
#define MINZ INT_MIN;
using namespace std;
int u[5010];
int v[5010];
int w[5010];
int frist[5010];
int next1[5010];
int dis[1010];
int visited[1010];
int n,m;
int maxz=-1;
void bellman(int s)
{
    dis[s]=0;
    queue < int > q;
    q.push(s);
    visited[s]=1;
    while (!q.empty())
    {
        int z=q.front();
        q.pop();
        int k=frist[z];
        visited[z]=0;
        while (k!=-1)
        {
            if(dis[v[k]]<dis[u[k]]+w[k])
            {
                dis[v[k]]=dis[u[k]]+w[k];
                maxz=max(maxz,dis[v[k]]);
                if(!visited[v[k]])
                {
                    q.push(v[k]);
                    visited[v[k]]=1;
                }
            }
            k=next1[k];
        }
    }
}
int main()
{
    cin>>n>>m;
    memset(frist,-1,sizeof(frist));
    for(int i=1;i<=m;i++)
    {
        cin>>u[i]>>v[i]>>w[i];
        next1[i]=frist[u[i]];
        frist[u[i]]=i;
    }
    for(int i=1;i<=n;i++)
        dis[i]=MINZ;
    for(int i=1;i<=n;i++)
    {
        bellman(i);
        for(int i=1;i<=n;i++)
            dis[i]=MINZ;
    }
    cout<<maxz;
}

邻接表思路:

#include<bits/stdc++.h>
#define MAXN 10000
using namespace std;
long long sum=0;
long long maxz=0;
int visited[MAXN];
int n,m;
struct node
{
    int u,v,w;
}a[MAXN];
int frist[MAXN],next1[MAXN];
void dfs(int z,long long op)
{
    int k=frist[z];
    while (k!=-1)
    {
        sum=max(sum,op+a[k].w);
        dfs(a[k].v,op+a[k].w);
        k=next1[k];
    }
}
int main()
{
    cin>>n>>m;
    memset(frist,-1,sizeof(frist));
    memset(visited,0,sizeof(visited));
    for(int i=1;i<=m;i++)
    {
         cin>>a[i].u>>a[i].v>>a[i].w;
         visited[a[i].v]=1;
         next1[i]=frist[a[i].u];
         frist[a[i].u]=i;
    }
    for(int i=1;i<=n;i++)
    {
        if(!visited[i])
        {
             dfs(i,0);
             maxz=max(maxz,sum);
             sum=0;
        }
    }
    cout<<maxz;
}

猜你喜欢

转载自blog.csdn.net/qq_40938077/article/details/81146648