ACM之最短路径做题笔记与记录
在这里纪念一下从4月开始一直因为事情而荒废了的最短路,多亏了jbb的帮助,我才完成了FZU热身赛一题简单的一个用模拟链表存边以及最短路径的学习,目前(6.5)已经学会使用了最简单的djstral与spfa,以及优先队列优化的dj,这里是最近2天做出来的题目,在这里记录一下
这题需要注意的就是可能存在回路,头尾一个点
//dijkstral + 动态数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int INF = 10000000;
struct E
{
int to;
int d;
};
int main()
{
int N;
while (scanf("%d",&N),N!=-1)
{
char s1[100],s2[100];
vector<E>head[160];
map<string,int> mp;
scanf("%s %s",s1,s2);
mp[s1] = 1;
mp[s2] = 2;
int len = 3;
bool flag = strcmp(s1,s2) == 0;
for (int i = 1; i < N + 1; i++)
{
int d;
scanf("%s %s %d",s1,s2,&d);
if(!mp[s1])
{
mp[s1] = len++;
}
if(!mp[s2])
{
mp[s2] = len++;
}
int u = mp[s1];
int v = mp[s2];
E tmp;
tmp.d = d;
tmp.to = u;
head[v].push_back(tmp);
tmp.to = v;
head[u].push_back(tmp);
}
if(flag)
{
printf("0\n");
continue;
}
int d[160];
bool vis[160] = {false};
fill(d,d+160,INF);
d[1] = 0;
while(true)
{
int nod = -1;
for(int i = 1 ; i < len; i++)
{
if(!vis[i] && (nod == -1 || d[nod] > d[i]))
{
nod = i;
}
}
if(nod == -1) break;
vis[nod] = true;
for (int i = 0; i < head[nod].size(); i++)
{
if(d[head[nod][i].to] > d[nod] + head[nod][i].d)
{
d[head[nod][i].to] = d[nod] + head[nod][i].d;
}
}
}
if(d[2] == INF)
{
printf("-1\n");
}
else
printf("%d\n",d[2]);
}
}
//dijkstral + 模拟链表
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int INF = 10000000;
struct E
{
int to;
int d;
bool operator < (const E &T) const
{
return d < T.d;
}
};
int main()
{
int N;
while (scanf("%d",&N),N!=-1)
{
char s1[100],s2[100];
vector<E>head[160];
map<string,int> mp;
scanf("%s %s",s1,s2);
mp[s1] = 1;
mp[s2] = 2;
int len = 3;
bool flag = strcmp(s1,s2) == 0;
for (int i = 1; i < N + 1; i++)
{
int d;
scanf("%s %s %d",s1,s2,&d);
if(!mp[s1])
{
mp[s1] = len++;
}
if(!mp[s2])
{
mp[s2] = len++;
}
int u = mp[s1];
int v = mp[s2];
E tmp;
tmp.d = d;
tmp.to = u;
head[v].push_back(tmp);
tmp.to = v;
head[u].push_back(tmp);
}
if(flag)
{
printf("0\n");
continue;
}
int d[160];
fill(d,d+160,INF);
d[1] = 0;
priority_queue<E> que;
E tmp;
tmp.d = 0;
tmp.to = 1;
que.push(tmp);
while (!que.empty())
{
tmp = que.top();
que.pop();
int u = tmp.to;
if(d[u] < tmp.d) continue;
for(int i = 0; i < head[u].size(); i++)
{
int v = head[u][i].to;
if(d[v] > d[u] + head[u][i].d)
{
d[v] = d[u] + head[u][i].d;
E ttt;
ttt.d = d[v];
ttt.to = v;
que.push(ttt);
}
}
}
if(d[2] == INF)
{
printf("-1\n");
}
else
printf("%d\n",d[2]);
}
}
//SPFA
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
//lower_bound(a+1,a+1+len1,x) - a - 1;
typedef long long LL;
const int INF = 10000000;
using namespace std;
struct E
{
int cost;
int nod;
};
int main()
{
// freopen("xx.in","r",stdin);
// freopen("xx.out","w",stdout);
int N;
while (scanf("%d",&N),N!=-1)
{
char a[100],b[100];
bool flag = false;
E edge[20010];
map<string,int> mp;
scanf("%s %s",a,b);
if(strcmp(a,b) == 0) flag = true;
mp[a] = 1;
mp[b] = 2;
int len = 3;
vector<int> head[160];
for (int i = 1; i < N + 1 ; i++)
{
int d;
scanf("%s %s %d",a,b,&d);
if(!mp[a])
{
mp[a] = len++;
}
if(!mp[b])
{
mp[b] = len++;
}
int u = mp[a];
int v = mp[b];
head[u].push_back(i);
edge[i].cost = d;
edge[i].nod = v;
head[v].push_back(i+N);
edge[i+N].cost = d;
edge[i+N].nod = u;
}
queue<int> que;
int d[160];
fill(d,d+160,INF);
d[1] = 0;
que.push(1);
bool vis[160] = {false};
vis[1] = true;
while(!que.empty())
{
int u = que.front();
vis[u] = false;
que.pop();
for (int i = 0; i < head[u].size(); i++)
{
int t = head[u][i];
if(d[edge[t].nod] > d[u] + edge[t].cost)
{
d[edge[t].nod] = d[u] + edge[t].cost;
if(!vis[edge[t].nod])
{
vis[edge[t].nod] = true;
que.push(edge[t].nod);
}
}
}
}
if(flag)
{
printf("0\n");
}
else
{
if(d[2] == INF)
{
printf("-1\n");
}
else
{
printf("%d\n",d[2]);
}
}
}
return 0;
}
这题比较有意思,我一开始不会做,题意大概是,给你N个货币类型,接下来M个货币兑换,问你是否存在一种情况,结果多次兑换后,你可以赚钱,比如一开始美元是1,你换来换去后可以把1美元变成大于1美元的情况...
这题据说不可以用djkstral,因为乘法中,小于1表示有负环,..所以用SPFA来弄,当然Floyd也可以,不过我还并不会...
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
//lower_bound(a+1,a+1+len1,x) - a - 1;
typedef long long LL;
using namespace std;
vector<int>head[40];
struct E
{
double cost;
int nod;
}edge[10000];
bool SPFA(int start)
{
bool vis[40] = {false};
double d[40] = {0};
d[start] = 1.0;
queue<int> que;
que.push(start);
while(!que.empty())
{
int u = que.front();
que.pop();
vis[u] = false;
for (int i = 0; i < head[u].size(); i++)
{
int t = head[u][i];//边
int v = edge[t].nod;
double cost = edge[t].cost;
if(d[v] < d[u]*cost)
{
d[v] = d[u]*cost;
vis[v] = true;
que.push(v);
}
}
if(d[start] > 1.0)
{
return true;
}
}
return false;
}
int main()
{
// freopen("xx.in","r",stdin);
// freopen("xx.out","w",stdout);
int N;
int T = 1;
while(scanf("%d",&N)!=EOF && N > 0)
{
char a[100],b[100];
memset(edge,0,sizeof(0));
map<string,int>mp;
for(int i = 0; i < 40; i++) head[i].clear();
for (int i = 1; i < N + 1; i++)
{
scanf("%s",a);
mp[a] = i;
}
int M;
double cost;
scanf("%d",&M);
for (int i = 1; i < M + 1 ; i++)
{
scanf("%s %lf %s",a,&cost,b);
int u = mp[a];
int v = mp[b];
head[u].push_back(i);
edge[i].cost = cost;
edge[i].nod = v;
}
bool flag = false;
for (int i = 1; i < N+1; i++)
{
if(SPFA(i))
{
flag = true;
break;
}
}
printf("Case %d: ",T++);
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
也是裸题
//SPFA
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <stack>
//lower_bound(a+1,a+1+len1,x) - a - 1;
typedef long long LL;
using namespace std;
const int INF = 10000000;
struct E
{
int to;
int cost;
};
int main()
{
// freopen("xx.in","r",stdin);
// freopen("xx.out","w",stdout);
int M,N;
while (scanf("%d %d",&N,&M)!=EOF)
{
E edge[20020];
vector<int> head[205];
for(int i = 1 ; i <= M; i++)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
head[u].push_back(i);
edge[i].to = v;
edge[i].cost = d;
head[v].push_back(i+M);
edge[i+M].to = u;
edge[i+M].cost = d;
}
int S,T;
scanf("%d%d",&S,&T);
int d[205];
fill(d,d+205,INF);
d[S] = 0;
queue<int> que;
bool vis[205] = {false};
que.push(S);
while(!que.empty())
{
int u = que.front();
que.pop();
vis[u] = false;
for (int i = 0; i < head[u].size(); i++)
{
int v = edge[head[u][i]].to;
int cost = edge[head[u][i]].cost;
if(d[v] > d[u] + cost)
{
d[v] = d[u] + cost;
if(!vis[v])
{
vis[v] = true;
que.push(v);
}
}
}
}
if(d[T] == INF)
{
printf("-1\n");
}
else
{
printf("%d\n",d[T]);
}
}
return 0;
}
同样裸题
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <stack>
//lower_bound(a+1,a+1+len1,x) - a - 1;
typedef long long LL;
using namespace std;
const int INF = 10000000;
struct E
{
int to;
int cost;
};
int main()
{
// freopen("xx.in","r",stdin);
// freopen("xx.out","w",stdout);
int M,N;
while (scanf("%d %d",&N,&M),M||N)
{
E edge[20020];
vector<int> head[205];
for(int i = 1 ; i <= M; i++)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
head[u].push_back(i);
edge[i].to = v;
edge[i].cost = d;
head[v].push_back(i+M);
edge[i+M].to = u;
edge[i+M].cost = d;
}
int d[205];
fill(d,d+205,INF);
d[1] = 0;
queue<int> que;
bool vis[205] = {false};
que.push(1);
while(!que.empty())
{
int u = que.front();
que.pop();
vis[u] = false;
for (int i = 0; i < head[u].size(); i++)
{
int v = edge[head[u][i]].to;
int cost = edge[head[u][i]].cost;
if(d[v] > d[u] + cost)
{
d[v] = d[u] + cost;
if(!vis[v])
{
vis[v] = true;
que.push(v);
}
}
}
}
printf("%d\n",d[N]);
}
return 0;
}
更新日志
|时间 | 更新模块 |
|---------------- | ----------- --- |
|6.5 | 3道裸题 |
|6.6 | 1道裸题 |
ACM之最短路径做题笔记与记录的更多相关文章
- LCT做题笔记
最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...
- SAM 做题笔记(各种技巧,持续更新,SA)
SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
- C语言程序设计做题笔记之C语言基础知识(上)
C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...
- SDOI2017 R1做题笔记
SDOI2017 R1做题笔记 梦想还是要有的,万一哪天就做完了呢? 也就是说现在还没做完. 哈哈哈我竟然做完了-2019.3.29 20:30
- SDOI2014 R1做题笔记
SDOI2014 R1做题笔记 经过很久很久的时间,shzr又做完了SDOI2014一轮的题目. 但是我不想写做题笔记(
- SDOI2016 R1做题笔记
SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...
- java做题笔记
java做题笔记 1. 初始化过程是这样的: 1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化: 2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序 ...
- PKUWC/SC 做题笔记
去年不知道干了些啥,什么省选/营题都没做. 现在赶应该还来得及(?) 「PKUWC2018」Minimax Done 2019.12.04 9:38:55 线段树合并船新玩法??? \(O(n^2)\ ...
随机推荐
- HDU 1158 Employment Planning
又一次看题解. 万事开头难,我想DP也是这样的. 呵呵,不过还是有进步的. 比如说我一开始也是打算用dp[i][j]表示第i个月份雇j个员工的最低花费,不过后面的思路就完全错了.. 不过这里还有个问题 ...
- HDU 1317 XYZZY【Bellman_Ford判断正环】
题意:给出n个房间,初始在房间1有100的能量值,每次进入一个房间,能量值可能增加也可能减小,(是点权,不是边权),问能否到达终点的时候能量值还为正 这题自己写的时候wa--wa-- 后来看了题解,还 ...
- iPad中控制器view初始的width和height
1> 规律 * width 是宽高中最小的那个值 * height 是宽高中最大的那个值 2> 举例(比如窗口根控制器的view,有状态栏的情况下) * 横屏 width = 748,h ...
- Linux Shell编程(4): 逻辑运算符、逻辑表达式详解
shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决我们很多复杂的判断,达到事半功倍效果. 一.逻辑运算符 逻辑卷标 表示意思 1. 关于档案与目录的侦测逻辑卷标! -f 常用!侦测 ...
- Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL
本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/644396 本博客已迁移到本人独立博客: http://www.yun5u ...
- 嵌入式 GDB调试死锁示例
死锁:一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被 其他线程占用并堵塞了的资源.例如,如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线 ...
- 关于TCP/UDP缓存
1.修订单个socket的缓冲区大小:通过setsockopt使用SO_RCVBUF来设置接收缓冲区,该参数在设置的时候不会与rmem_max进行对比校验,但是如果设置的大小超过rmem_max的话, ...
- CMake实践(4)
一,本期目标: [sun@localhost t4]$ cat README 任务:如何使用外部共享库和文件 二,目录结构 [sun@localhost t4]$ tree ../t4../t4├── ...
- 10、NFC技术:读写NFC标签中的文本数据
代码实现过程如下: 读写NFC标签的纯文本数据.java import java.nio.charset.Charset; import java.util.Locale; import androi ...
- .net发邮件 附件文件名乱码
.net发邮件 附件文件名乱码,可以下载以下补丁安装. https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.asp ...