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

来源:互联网 发布:外贸邦海关数据有用吗 编辑:程序博客网 时间:2024/06/05 05:30
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;                }            }        }






原创粉丝点击