解题思路:
动规方程:f[i]=max(f[j]+a[i]),有j到i的边。
输出方案可把每个点记一个前驱pre[i],回溯输出。
多组数据,注意清零,特别是a[n+1]=0。
最后一行不能再打空行,不然要PE。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=105;
int T,n,m;
int a[N],f[N],pre[N];
bool g[N][N];
void W(int x)
{
if(x==1)
{
putchar('1');
return;
}
W(pre[x]);
if(x==n)printf("->1\n");
else printf("->%d",x);
}
int main()
{
//freopen("lx.in","r",stdin);
T=getint();
for(int k=1;k<=T;k++)
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(pre,0,sizeof(pre));
n=getint();
for(int i=1;i<=n;i++)
a[i]=getint();
a[n+1]=0;
m=getint();
while(m--)g[getint()][getint()]=true;
n++;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(g[j][i]&&f[i]<f[j]+a[i])
f[i]=f[j]+a[i],pre[i]=j;
printf("CASE %d#\n",k);
printf("points : %d\n",f[n]);
printf("circuit : ");
W(n);
if(k!=T)putchar('\n');
}
return 0;
}