题意
给定第一行顶点个数, 第二行0->山, 1->宾馆, 第三行 每个值->下标 表示链接一条边
找一条满足以下条件的最长路:
- 起点是山, 终点是宾馆
- 相邻两个顶点仅有一条确切的路
- 包含尽可能多的项目
输出第一行项目总数, 第二行路径
题解
感觉是贪心版的最短路变形, 反向建图, 从宾馆开始找山, 找到一条满足条件的最长路的同时记录路径, 遍历所有宾馆, 也就找到了最优解, 逆序输出路径即可
代码
正常版本
#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;
}