题目大意:题目链接
weiwei要出去环游世界了!但并不是每个景点之间都有直达的飞机的,每个景点都有一个有趣值,而且weiwei最后必须回到他的出发点(毕竟环游嘛)题目中把1和n+1均设为出发点,给出每个景点的有趣值以及哪些景点之间有直达的飞机,注意的是,编号大的景点不会有直达的飞机到编号小的景点。求如何规划路线才能使weiwei获得最大的有趣值。
题目:
题目思路:
1、一个比较令人欣喜的信息是:从编号大的景点不会有直达飞机到编号小的景点。这就是说,这道题我们要建的是一个有向图!那么如果1号景点值为0,下一个是2号景点,值为90,而且1 2之间有一直达飞机,那么我们就可以把1——>2的这条边边权设为2号景点的有趣值90。也就是说我们每次都可以把一条边中后面节点的有趣值当作这条边的权值。
2、根据题意,问题转化为求出从1号景点到n+1号景点的最长路。dijkstra由于不能保证最优子结构的原因无法用来求最长路,(不过这道题似乎不影响),而Bellman-Ford算法时间复杂度高达O(nm),SPFA是它的优化算法,这里我们选择用SPFA算法来求最长路。
3、第三个问题就是如何输出路径,当初写BFS输出路径的问题就被折磨颇深,这个思路也类似。用一个fa[]数组每次保存这个节点的上一个节点是谁。最后的节点肯定是n+1,最开始的节点肯定是1,这样依次找下去即可。嫌麻烦的话用一个栈就好。
比较坑的一点就是!输出格式!!题目中说的是在两个测试点之间输出一个空行,但是……最后一个测试点之后不用输出空行,,因为下一个没有测试点了,也就不存在两个之间了……(真心猥琐……
题目代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#define maxn 205
using namespace std;
int val[maxn];
int dis[maxn];
bool vis[maxn];
int fa[maxn];
struct Edge //保存边的信息
{
int u,v,w;
Edge(int uu,int vv,int ww):u(uu),v(vv),w(ww){}
};
vector<Edge>e[maxn<<1];
queue<int>q;
stack<int>st;
int n,m;
void print()
{
for(int i=fa[n+1];i!=1;i=fa[i])//因为输出的数字不能是n+1,而是1,所以从fa[n+1]开始
st.push(i);
printf("1->");
while(!st.empty())
{
int mid=st.top();
st.pop();
printf("%d->",mid);
}
printf("1\n");
}
void spfa(int s)//spfa算法模板
{
q.push(s);
vis[s]=true;dis[s]=0;
while(!q.empty())
{
int mid=q.front();q.pop();
vis[mid]=false;
for(int i=0;i<e[mid].size();i++)
{
int nxt=e[mid][i].v;
if(dis[nxt]<dis[mid]+e[mid][i].w)
{
dis[nxt]=dis[mid]+e[mid][i].w;
fa[nxt]=mid;//记录父亲是谁
if(!vis[nxt])
{
q.push(nxt);
vis[nxt]=true;
}
}
}
}
}
int main(void)
{
int t;
int a,b;
scanf("%d",&t);
for(int t1=1;t1<=t;t1++)
{
scanf("%d",&n);
memset(dis,-1,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(val,0,sizeof(val));
memset(fa,0,sizeof(fa));
for(int i=1;i<=n+1;i++)
e[i].clear();
//一定记得初始化
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
}
val[n+1]=val[1];
//
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
e[a].push_back(Edge{a,b,val[b]});//有向图
}
//
spfa(1);
printf("CASE %d#\npoints : %d\n",t1,dis[n+1]);
printf("circuit : ");
print();//输出路线
if(t1!=t)
printf("\n");
}
return 0;
}
/*
2
4
0 70 90 30
6
1 2
1 3
2 4
3 4
4 5
3 5
*/
呼呼