2017暑假集训 div1 最短路(1)

POJ 2253
题目:给出两只青蛙的坐标A、B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的。显然从A到B存在至少一条的通路,每一条通路的元素都是这条通路中前后两个点的距离,这些距离中又有一个最大距离。
现在要求求出所有通路的最大距离,并把这些最大距离作比较,把最小的一个最大距离作为青蛙的最小跳远距离。

做法: 这是最短路的变形,每两点之间都有路可以跳,更新最短路的值,权值记录成目前到这一点的最小青蛙距离就行了。

核心代码:
 for(int i=1;i<=n;++i)
        {
            double temp=max(dis[u],map[u][i]);
            if(u!=i&&dis[i]>temp)
            {
                dis[i]=temp;
                if(!vis[i])
                {
                    vis[i]=1; que.push(i);
                }
            }
        }


POJ 1797
题目:有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而最大承载量就是从城市1到城市n所有通路上的最大承载量

做法:其实这个求最大边可以近似于求最短路,只要修改下找最短路更新的条件就可以了

核心代码:
 for(int j=1;j<=n;++j)
        {
            if(j!=pos&&weg[j]<min(weg[pos],map[pos][j]))
            {
                weg[j]=min(weg[pos],map[pos][j]);
            }
        }


POJ 3268
题目:给出n个点和m条边,接着是m条边,代表从牛a到牛b需要花费c时间,现在所有牛要到牛x那里去参加聚会,并且所有牛参加聚会后还要回来,给你牛x,除了牛x之外的牛,他们都有一个参加聚会并且回来的最短时间,从这些最短时间里找出一个最大值输出
做法:正着一遍最短路存起来反着一遍最短路(地图取反),扫一遍求所有牛两次最短路的和的最大值

核心代码:
    dij();
    for(int i=1;i<=n;++i)
    {
        for(int j=i;j<=n;++j)
        {
            swap(map[i][j],map[j][i]);
        }
    }
    dij();
    int a=0;
    for(int i=1;i<=n;++i)
    {
        a=max(a,ans[i]);
    }
    printf("%d\n",a);

POJ 3259
题意:给你三个数n,m,w,分别表示有n个农场,m条路,w个黑洞,接下来m行分别有三个数s,e,val表示s到e有一条权值为val 的边,接下来的w行每行有三个数s,e,val表示s到e有一条权值为0-val的边,因为黑洞可以回到过去,所以其权值为负。现在问你给你这些点,求每组数据是否存在一条回路能使时间倒退。

做法:判断是否存在负环, 用spfa 跑一遍,只需要判断是否有点进入队列 n 次 如果有存在负环!

核心代码:
            if(dis[v]>dis[u]+edge[i].w)
            {
                dis[v]=dis[u]+edge[i].w;
                if(!vis[v])
                {
                    du[v]++;
                    vis[v]=1;
                    que.push(v);
                    if(du[v]>=n)
                    {
                        printf("YES\n");
                        return ;
                    }
                }
            }

POJ 1860
题意:有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的
 
做法:判断正环,把负环的条件取反即可,初始化为0,每次判断是否大于。依旧是判断是否入队n次


核心代码:
for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            double value = ( w[u]-edge[i].v )* edge[i].r;
            if(value > w[v])
            {
                w[v]=value;
                if(!vis[v])
                {
                    vis[v]=1; du[v]++; que.push(v);
                    if(du[v]>=n) return 1;
                }
            }
        }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值