• POJ 1062 【带约束的最短路问题】


    中文题题意不写。

    建图:

    我自己想到的建图方式是把每个物品看作两个点,编号分别是i和i+n,然后每个物品两个点之间边的权值是物品本身的价值。然后从第i个点往外连边,目标是可替代品顶点编号较小的点,权值为替代之后的优惠费用,然后将可替代品的顶点编号较大的点连向第i+n个顶点,权值是0.

    这种建图方法将点的数量增加为原来的两倍,边的数量也相应增加,所以并不是好的建图方法。

    大牛的建图方法是把旅行家看作是一个顶点,边的出路是每个物品,权值是每个物品对应的价值,然后当有物品可以有替代物品的时候,连边,起点是替代物,终点是被替代物品,权值是替代后的优惠价格。

    这种建图方法更加稠密,同时节点的数量也少。

    这道题需要注意的是连接是单向边。

    对于约束的处理是,参考了大牛的思想。从第一个节点枚举到第n个节点,以该节点的等级为最低等级,以该节点加m为最高等级,将在这个范围以外的顶点做vis=1的处理,反复进行最短路,取这些最短路的最小值。

    #include<stdio.h>
    #include<string.h>
    int max(int a,int b)
    {
        if(a>b)
            return a;
        return b;
    }
    int min(int a,int b)
    {
        if(a<b)
            return a;
        return b;
    }
    int m,n;
    int dis[205];
    bool vis[205];
    const int inf=999999999;
    int deg[205];
    int ednum;
    struct edge
    {
        int id,w;
        edge *next;
    };
    edge *adj[205];
    edge edges[5005];
    inline void addEdge(int a,int b,int c)
    {
        edge *tmp;
        tmp=&edges[ednum];
        ednum++;
        tmp->id=b;
        tmp->w=c;
        tmp->next=adj[a];
        adj[a]=tmp;
    }
    void solve(int pos)
    {
        vis[pos]=1;
        for(edge *p=adj[pos]; p; p=p->next)
        {
            if((!vis[p->id]))
            {
                if((p->w)+dis[pos]<dis[p->id])
                {
                    dis[p->id]=(p->w)+dis[pos];
                }
            }
        }
        int next=inf;
        int minn=inf;
        for(int i=1; i<=2*n; i++)
        {
            if(!vis[i]&&minn>dis[i])
            {
                minn=dis[i];
                next=i;
            }
        }
        if(next<=2*n)
        {
            solve(next);
        }
    }
    int main()
    {
        int num,id,tmon,up,low;
        int aa,bb,cc,dd;
        int rel=inf;
        scanf("%d%d",&m,&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d",&aa,&bb,&cc);
            addEdge(i,i+n,aa);
            deg[i]=deg[i+n]=bb;
            for(int  j=1; j<=cc; j++)
            {
                scanf("%d%d",&id,&tmon);
                addEdge(i,id,tmon);
                addEdge(id+n,i+n,0);
            }
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=2*n; j++)
            {
                dis[j]=inf;
            }
            for(int j=1; j<=2*n; j++)
            {
                if(deg[j]>=deg[i]&&deg[j]<=deg[i]+m)
                {
                    vis[j]=0;
                }
                else
                {
                    vis[j]=1;
                }
            }
            dis[1]=0;
            solve(1);
            if(rel>dis[1+n])
                rel=dis[1+n];
        }
        printf("%d
    ",rel);
        return 0;
    }
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/tun117/p/4821192.html
Copyright © 2020-2023  润新知