这题真是八仙过海
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缩点
我不想打了...