CodeForces_350BResort ( 最短路思想_贪心_路径输出 )

题目连接 -> cf and vj

题意

给定第一行顶点个数, 第二行0->山, 1->宾馆, 第三行 每个值->下标 表示链接一条边
找一条满足以下条件的最长路:

  1. 起点是山, 终点是宾馆
  2. 相邻两个顶点仅有一条确切的路
  3. 包含尽可能多的项目

输出第一行项目总数, 第二行路径

题解

感觉是贪心版的最短路变形, 反向建图, 从宾馆开始找山, 找到一条满足条件的最长路的同时记录路径, 遍历所有宾馆, 也就找到了最优解, 逆序输出路径即可

代码

在这里插入图片描述

正常版本

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 100005;

int isHotle[MAXN], link[MAXN];
int inDegree[MAXN], path[MAXN];
int tempPath[MAXN];



int main ( ) {

	int n;

	while ( ~scanf ( "%d", &n ) ) {

		memset ( inDegree, 0, sizeof(inDegree) );

		for ( int i = 1; i <= n; ++i )
			scanf ( "%d", &isHotle[i] );
		for ( int i = 1; i <= n; ++i ) {
			scanf ( "%d", &link[i] ); // value -> index 指的是一条路
			inDegree[link[i]]++; ///记录这个点是否是单条路线的点
		}

		int maxItems = 0;               
		for ( int i = 1; i <= n; ++i ) { // 假定从宾馆出发, 终点为山, 找到最长无岔口的路后逆序输出

			if ( !isHotle[i] ) continue; 

			int u = i, v = link[u]; // 既然是反向建图, 那么就是 index -> value 指的是一条路

			int items = 0;  tempPath[items++] = u;

			while ( v && inDegree[v]<=1 ) { 
				tempPath[items++] = v;
				u = v, v = link[u];
			}

			if ( items > maxItems ) {
				maxItems = items;
				for ( int j = 0; j < maxItems; ++j )
					path[j] = tempPath[j];
			}

		}

		printf ( "%d\n", maxItems );
		for ( int i = maxItems-1; i >= 0; --i )
			printf ( "%d ", path[i] );
		puts ( "" );


	}






	return 0;
}

瞎搞的优化…还更慢了…

#include <bits/stdc++.h>
using namespace std;
#define rg register
#define sc scanf
#define pf printf

const int MAXN = 100005;

bool isHotel[MAXN]; int hotel[MAXN], link[MAXN];
int inDegree[MAXN], path[MAXN];
int tempPath[MAXN];



int main ( ) {

	int n;

	while ( ~scanf ( "%d", &n ) ) {

		memset ( inDegree, 0, sizeof(inDegree) );

        int totHotel = 0;
		for ( int i = 1; i <= n; ++i ) {
			scanf ( "%d", &isHotel[i] ); 
            if ( isHotel[i] ) hotel[totHotel++] = i; // 这里是优化查找宾馆的时间
        }
		for ( int i = 1; i <= n; ++i ) {
			scanf ( "%d", &link[i] ); // value -> index 指的是一条路
			inDegree[link[i]]++; 
		}

		int maxItems = 0;               
		for ( int i = 0; i < totHotel; ++i ) {// 假定从宾馆出发反向建图, 终点为山, 找到最长无岔口的路后逆序输出

                                                            //  u   ->   v
            int u = hotel[i], v = link[u]; // 既然是反向建图, 那么就是 index -> value 指的是一条路

            int items = 0; tempPath[items++] = u;

            while ( v && inDegree[v]<=1 ) { 
                tempPath[items++] = v;
                u = v, v = link[u];
            }

            if ( items > maxItems ) {
                maxItems = items;
                for ( int j = 0; j < maxItems; ++j )
                    path[j] = tempPath[j];
            }

		}

		printf ( "%d\n", maxItems );
		for ( int i = maxItems-1; i >= 0; --i )
			printf ( "%d ", path[i] );
		puts ( "" );


	}






	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值