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)\ ...
随机推荐
- myeclipes准备工作
设置jsp中默认编码为utf-8
- yii2.0 事务
$transaction=\Yii::$app->db->beginTransaction(); $model=Customer::findOne(1); $model->name= ...
- ORACLE 常用SQL查询
一.ORACLE的启动和关闭 1 .在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a.启动ORACLE系统 oracle > sv ...
- Thrift——初学
是什么? Thrift是一个跨语言的服务部署框架最初由Facebook于2007年开发,2008年进入Apache开源项目.Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数 ...
- Android Window 9问9答
1.简述一下window是什么?在android体系里 扮演什么角色? 答:window就是一个抽象类,他的实现类是phoneWindow.我们一般通过windowManager 来访问window. ...
- @错误抑制运算符和or die()
1.错误抑制运算符可在任何表达式前使用,PHP支持一个错误抑制运算符@.当将其放置在一个PHP表达式之前,则该表达式可能产生的任何错误信息都被忽略掉.@运算符只对表达式有效. 2.or die() 当 ...
- (win+linux)双系统,删除linux系统的条件下,删除grub引导记录,恢复windows引导
//(hdx,y) (显示查找到的分区号)第一个数字指第几个硬盘,第二个指第几个分区. 一般我们是(hd0,0) \n Linux的分区已经被你从Windows中删除,系统启动后停在“grub&g ...
- JDBC用ResultSet访问大量数据时会遇到的问题
我们经常需要JDBC来对数据库就行操作,一般流程为连接数据库.通过sql语句把需要的数据取出来保存到ResultSet,然后调用ResultSet方法的类似 getString,getInt()等方法 ...
- ylb:表的结构的修改和基本约束
ylbtech-SQL Server:SQL Server-表的结构的修改和基本约束 SQL Server 表的结构的修改和基本约束. 1,表的结构的修改和基本约束返回顶部 use master go ...
- VC远控(三)磁盘显示
服务端: 发送与接收命令 DWORD WINAPI SLisen(LPVOID lparam) { SOCKET client = (SOCKET)lparam; COMMAND command; w ...