图与树
图 有向图 无向图
树 特殊的无向图,每边有一个长度
顶点 n,边 m(n,m的数据范围1e5)
图的储存方式:邻接矩阵 邻接表
树 n个节点的图中,有n-1条边
连接图的边,把这些点连起来,恰好可以联通
树的储存方式:
1. 无向图
2. 父亲节点表示法 fa[x]
3. 儿子节点表示法 son[root][n-1](不高效)
4. 左儿子右亲兄弟——树转二叉树
图的遍历:BFS、DFS
图的最短路算法——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发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。
农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)
输入输出格式
输入格式:
第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)
第二行到第N+1行: 1到N头奶牛所在的牧场号
第N+2行到第N+C+1行:每行有三个数:相连的牧场A、B,两牧场间距离D(1<=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;
}