【刷题】【图论】最优贸易【未完成】

拟墨画扇 提交于 2019-12-01 08:12:49

这题真是八仙过海

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;
}
View Code

 

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缩点 

我不想打了...

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!