思路:最短路+SOFA
分析:
1 提要要求的最大的环,蛋并不是这么的复杂,因为第一个点的points值为0,所以其实就是求1到某一个点的最长路,其实就是最长路问题
2 注意的是在求1到某一个点的最长路的时候还要注意这个点是否能够到达1点,这个可以用一个mark数组来标记
3 可以更简单的做法就是1-n+1的最长路。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 110
#define INF 0xFFFFFFF
int t , n , m;
int num[MAXN];
int path[MAXN];
int father[MAXN];
int value[MAXN][MAXN];
int dis[MAXN];
int mark[MAXN];
int vis[MAXN];
queue<int>q;
void SPFA(){
memset(vis , 0 , sizeof(vis));
memset(dis , 0 , sizeof(dis));
memset(num , 0 , sizeof(num));
father[1] = father[n] = 1;
vis[1] = 1;
q.push(1);
while(!q.empty()){
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = 1 ; i <= n ; i++){
if(value[x][i] && dis[i] < dis[x] + value[x][i]){
dis[i] = dis[x] + value[x][i];
father[i] = x;
if(!vis[i]){
vis[i] = 1;
q.push(i);
}
}
}
}
}
int main(){
int i , j , a , b , cnt;
int pos , ans;
scanf("%d" , &t);
for(i = 1 ; i <= t ; i++){
/*输入n个城市的points*/
scanf("%d" , &n);
memset(value , 0 , sizeof(value));
memset(mark , 0 , sizeof(mark));/*标记为0*/
for(j = 1 ; j <= n ; j++)
scanf("%d" , &num[j]);
/*输入边的关系*/
scanf("%d" , &m);
for(j = 0 ; j < m ; j++){
scanf("%d%d" , &a , &b);
if(b == n+1){
mark[a] = 1;
continue;
}
value[a][b] = num[b];
}
/*求SPFA*/
SPFA();
/*求最大值的点*/
ans = 0;
pos = 1;
for(j = 2 ; j <= n ; j++){
if(mark[j] && ans < dis[j]){
ans = dis[j];
pos = j;
}
}
/*求路径path*/
a = pos;
cnt = 0;
memset(path , 0 , sizeof(path));
path[cnt++] = pos;
while(1){
b = father[a];
if(b == 1)
break;
path[cnt++] = b;
a = b;
}
/*输出*/
printf("CASE %d#\n" , i);
printf("points : %d\n" , ans);
printf("circuit : 1");
for(j = cnt-1 ; j >= 0 ; j--)
printf("->%d" , path[j]);
printf("->1\n");
if(i < t)
printf("\n");
}
return 0;
}