【最短路/3大模板】总结【2012-1-22新增前插的spfa】

12 篇文章 0 订阅
10 篇文章 0 订阅
[img]http://dl.iteye.com/upload/attachment/544682/0ca3f693-db83-35da-b50e-b0c8f7acc4d8.png[/img]


[size=medium]首先献上模板:【点都是默认为从1到n编号,用dijk和floyd时要注意重边】
①DIJK[/size]

#define inf 0x3fffffff
#define M 105

int dist[M], map[M][M], n;
bool mark[M];

void init ()
{
int i, j;
for (i = 1; i <= n; i++) //i==j的时候也可以初始化为0,只是有时候不合适
for (j = 1; j <= n; j++)
map[i][j] = inf;
}

void dijk (int u)
{
int i, j, mins, v;
for (i = 1; i <= n; i++)
{
dist[i] = map[u][i];
mark[i] = false;
}
mark[u] = true;
dist[u] = 0; //既然上面的map当i==j时不是0,就要这句
while (1)
{
mins = inf;
for (j = 1; j <= n; j++)
if (!mark[j] && dist[j] < mins)
mins = dist[j], v = j;
if (mins == inf)
break;
mark[v] = true;
for (j = 1; j <= n; j++)
if (!mark[j] && dist[v] + map[v][j] < dist[j])
dist[j] = dist[v] + map[v][j];
}
}

[size=medium]②Floyd[/size]

#define inf 0x3fffffff //注意,太大会溢出
#define M //最大点数
int n, dist[M][M]; //n:实际点数

void init () //有时候需要初始化
{
int i, j;
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
dist[i][j] = dist[j][i] = inf;
}

void floyd ()
{
int i, j, k;
for (k = 1; k <= n; k++)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) //有的题目会溢出就要自己变通了
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}

[size=medium]③vector后插的SPFA[/size]

#define inf 0x3fffffff
#define M 105 //最大点数
struct son{
int v, w;
};
vector<son> g[M];
bool inq[M]; //入队列标记
int dist[M], n; //n:实际点数

void init ()
{
for (int i = 1; i <= n; i++)
g[i].clear();
}

void spfa (int u)
{
int i, v, w;
for (i = 1; i <= n; i++)
{
dist[i] = inf;
inq[i] = false;
}
queue<int> q;
q.push (u);
inq[u] = true;
dist[u] = 0;
while (!q.empty())
{
u = q.front();
q.pop();
inq[u] = false;
for (i = 0; i < g[u].size(); i++)
{
v = g[u][i].v;
w = g[u][i].w;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
if (!inq[v])
{
q.push (v);
inq[v] = true;
}
}
}
}
}

[size=medium]④模拟前插的SPFA(多数情况下比③快,数据较为复杂就会看出来)[/size]

#define inf 0x3fffffff
#define M 1005 //最大点数

struct edge{
int v, w, next;
}e[10005]; //估计好有多少条边

int pre[M], cnt, dist[M], n;
bool inq[M];
//注意初始化
void init ()
{
cnt = 0;
memset (pre, -1, sizeof(pre));
}
//注意双向加边
void addedge (int u, int v, int w) //加边函数,慢慢模拟就会明白的
{
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = pre[u]; //接替已有边
pre[u] = cnt++; //自己前插成为u派生的第一条边
}

void spfa (int u)
{
int v, w, i;
for (i = 1; i <= n; i++) //对于从1到n的编号
dist[i] = inf, inq[i] = false;
dist[u] = 0;
queue<int> q;
q.push (u);
inq[u] = true;
while (!q.empty())
{
u = q.front();
q.pop();
inq[u] = false;
for (i = pre[u]; i != -1; i = e[i].next)
{
w = e[i].w;
v = e[i].v;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
if (!inq[v])
{
q.push (v);
inq[v] = true;
}
}
}
}
}


[b][size=medium][color=green]第一题:[url]http://acm.hdu.edu.cn/showproblem.php?pid=2544[/url][/color]
灰常水,floyd、dijk、spfa都可以

[color=green]第二题:[url]http://acm.hdu.edu.cn/showproblem.php?pid=2066[/url][/color]
简单题,多源多终点,spfa、dijk都很快解决

[color=green]第三题:[url]http://acm.hdu.edu.cn/showproblem.php?pid=2112[/url][/color]
用STL的map把地名映射到编号就可以套模板了,注意路是双向的就行了

[color=green]第四题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1874[/url]
和第一题一样的水

[color=green]第五题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1142[/url]
最短路+记忆化搜索
详情:[url]http://972169909-qq-com.iteye.com/blog/1149589[/url]


[color=green]第六题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1385[/url]
floyd记忆路径
详情:[url]http://972169909-qq-com.iteye.com/blog/1150803[/url]

[color=green]第七题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1548[/url]
水题,构图后直接dijk或spfa就可以了

[color=green]第八题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1217[/url]
floyd的灵活运用
详情:[url]http://972169909-qq-com.iteye.com/blog/1149095[/url]

[color=green]第九题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2680[/url]
简单题,多起点单终点,反过来dijk或者spfa就可以了,注意路是单向的,所有路都要反过来,逆向思维

[color=green]第十题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2923[/url]
题目意思可能比较难懂,而且有重边,floyd
详情:[url]http://972169909-qq-com.iteye.com/blog/1150818[/url]

[color=green]第十一题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2962[/url]
直接枚举或二分枚举+最短路
详情:[url]http://972169909-qq-com.iteye.com/blog/1159652[/url]

[color=green]第十二题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2722[/url]
这题主要是构图麻烦,会用sscanf就比较好做了,构好图之后就是水题了

[color=green]第十三题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1690[/url]
暴力构图,枚举2点间距离,根据表格定好花费,然后直接floyd就可以了【注意数太大要用64位,无穷大定为-1比较好处理】

[color=green]第十四题表示压力好大……[/color]

[color=green]第十五题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1596[/url]
floyd水题

[color=green]第十六题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=1598[/url]
并查集+贪心 或 二分枚举+最短路
详情:[url]http://972169909-qq-com.iteye.com/blog/1159593[/url]

[color=green]第十七题表示不想做……[/color]

[color=green]第十八题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2363[/url]
枚举高度差+最短路,比较容易错
详情:[url]http://972169909-qq-com.iteye.com/blog/1159650[/url]

[color=green]第十九题表示很蛋疼……[/color]

[color=green]第二十题:[/color][url]http://acm.hdu.edu.cn/showproblem.php?pid=2833[/url]
一题比较难的记忆化搜索+最短路【或dp+最短路】
详情:[url]http://972169909-qq-com.iteye.com/blog/1159661[/url]
[/size][/b]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值