luogu寒假pjday2部分

本文详细介绍Floyd算法在解决图论中最短路径问题的应用,并通过一个具体的编程实例展示算法的实现过程。

图与树

有向图 无向图

特殊的无向图,每边有一个长度

顶点 n, mn,m的数据范围1e5

 

图的储存方式:邻接矩阵 邻接表

 

n个节点的图中,有n-1条边

连接图的边,把这些点连起来,恰好可以联通

 

树的储存方式:

1.    无向图

2.    父亲节点表示法  fa[x]

3.    儿子节点表示法  son[root][n-1](不高效)

4.    左儿子右亲兄弟——树转二叉树

 

图的遍历:BFSDFS

 

图的最短路算法——Floyd(有向图、无向图、负权)

传递闭包

INF可表示为0x3f3f3f3f

 

初始化:

1. 不可以直接到达的dis设为正无穷(oo)

2. 自己到自己的距离为0

3. 题目给定的边的dis[i][j]直接赋值为该边长度。双向边需要dis[i][j]dis[j][i]均赋值为边长。

 

思想:

1.枚举中转节点。

2.检查由S点经过此点到T点的路径是否比原先优。

3.更新由S点到T点的最短距离。

 

Luogu P1828 香甜的黄油Sweet Butter

 

题目描述

农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。

农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。

农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)

输入输出格式

输入格式:

 

第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)

第二行到第N+1: 1N头奶牛所在的牧场号

N+2行到第N+C+1行:每行有三个数:相连的牧场AB,两牧场间距离D1<=D<=255),当然,连接是双向的

 

输出格式:

 

一行 输出奶牛必须行走的最小的距离和

 

输入

3 4 5

2

3

4

1 2 1

1 3 5

2 3 7

2 4 3

3 4 5

 

输出

8


#include <stdio.h>
#include <string.h>
int map[805][805];
int d[805][805];
int y[805];
#define INF 0x3f3f3f3f
 
int main()
{
       freopen("input.txt","r",stdin);
       intn,p,c,i,j,k,ans = INF;
       scanf("%d%d%d",&n,&p,&c);
       memset(y,0,sizeof(y));
       for(i= 0;i < p;i++)                             //初始化图
              for(j= 0;j < p;j++)
              {
                     if(i== j)
                     {
                            map[i][j]= 0;
                            d[i][j]= 0;
                     }
                     else
                     {
                            map[i][j]= INF;
                            d[i][j]= INF; 
                     }
              }
       for(i= 0;i < n;i++)
       {
              intx;
              scanf("%d",&x);
              y[x-1]++;
       }
       for(i= 0;i < c;i++)                      //读入图
       {
              intv,u,dis;
              scanf("%d%d%d",&v,&u,&dis);
              map[v-1][u-1]= dis;
              map[u-1][v-1]= dis;
              d[v-1][u-1]= dis;
              d[u-1][v-1]= dis;
       }
       for(k= 0;k < p;k++)                                        //Floyd(无向图另一半也要更新)
              for(i= 0;i < p;i++)
                     for(j= 0;j < i;j++)
                            if(d[i][k]+ d[j][k] < d[i][j])
                            {
                                   d[i][j]= d[i][k] + d[j][k];
                                   d[j][i]= d[i][j];
                            }
       for(i= 0;i < p;i++)
       {
              int sum = 0;
              for(j= 0;j < p;j++)
                     sum+= d[i][j]*y[j];
              if(sum< ans)
                            ans= sum;
       }
       printf("%d",ans);
       return0;


} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值