这题真是八仙过海
1>暴力,图上dp
看成一条条链,dp思路有点像spfa,有点记忆化的成分,
每次到一个点,如果结果/向下传的最小值变了,那么后面的状态才会改变,
所以这个剪枝 + f[rt]=max(f[rt] , f[pre] , val[rt]-mn );
然后就写出代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<cstring>
using namespace std;
int n,m;
const int N=5e4+3,M=1e5+3;
int tot,head[N];
struct node
{
int v,nx;
}e[M<<1];
void add(int u,int v)
{ e[++tot].v =v,e[tot].nx =head[u],head[u]=tot; }
inline int read()
{
int x=0;char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
int val[N],f[N],lst[N];
void dfs(int rt,int mn,int pre)
{
bool fg=false;
int t=min(mn,val[rt]);
if(t<lst[rt]) fg=true,lst[rt]=t;
t=max(f[pre],val[rt]-lst[rt]);
if(t>f[rt]) fg=true,f[rt]=t;
if(!fg) return ;
for(int i=head[rt];i;i=e[i].nx )
dfs(e[i].v ,lst[rt],rt);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) val[i]=read();
int u,v,w;
for(int i=1;i<=m;i++)
{
u=read(),v=read(),w=read(),add(u,v);
if(w==2) add(v,u);
}
memset(lst,0x3f,sizeof(lst));
dfs(1,lst[1],0);
printf("%d\n",f[n]);
return 0;
}
2>分层图,最短路
分三层,就是三种状态:
没买,买了没卖,卖了,
卖了就是值的相反数,卖了就是值,
然后建立图
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
int n,m;
const int N=5e4+3,M=1e5+3;
int tot,head[N*3];
struct node
{
int v,w,nx;
}e[M*10];
int ad1,ad2;
void add(int u,int v,int w)
{
e[++tot].v =v ,e[tot].nx =head[u ],e[tot].w = 0,head[u ]=tot;
e[++tot].v =v+ad1,e[tot].nx =head[u ],e[tot].w =-w,head[u ]=tot;
e[++tot].v =v+ad1,e[tot].nx =head[u+ad1],e[tot].w = 0,head[u+ad1]=tot;
e[++tot].v =v+ad2,e[tot].nx =head[u+ad1],e[tot].w = w,head[u+ad1]=tot;
e[++tot].v =v+ad2,e[tot].nx =head[u+ad2],e[tot].w = 0,head[u+ad2]=tot;
}
inline int read()
{
int x=0;char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
int val[N],dis[N*3];
struct nd
{
int v;
bool operator < (const nd & o) const
{ return dis[v] < dis[o.v] ; }
nd(int vv){ v=vv; }
nd(){}
};
bool in[N*3];
priority_queue <nd> q;
void dijk()
{
memset(dis,-0x3f,sizeof(dis));
dis[1]=0,q.push(nd(1));
while(!q.empty() )
{
int t=q.top() .v;q.pop() ;
for(int i=head[t];i;i=e[i].nx )
{
int nx=e[i].v ;
if(dis[nx]<dis[t]+e[i].w )
{
dis[nx]=dis[t]+e[i].w ;
if(!in[nx])
in[nx]=true,q.push(nd(nx));
}
}
in[t]=false;
}
}
int main()
{
n=read(),m=read();
ad1=n,ad2=n+n;
for(int i=1;i<=n;i++) val[i]=read();
int u,v,w;
for(int i=1;i<=m;i++)
{
u=read(),v=read(),w=read();
add(u,v,val[u]);
if(w==2) add(v,u,val[v]);
}
dijk();
printf("%d\n",max(dis[n*3],0));
return 0;
}
3>tarjan缩点
我不想打了...
