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道裸题 |