解题思路:
简单最短路
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100 + 5;
int N, M;
int Map[maxn][maxn];
bool vis[maxn];
int dis[maxn];
void Dijkstra(void);
int main()
{
// freopen("in.txt", "r", stdin);
while (cin>>N>>M && !(N==0&&M==0)) {
memset(vis, false, sizeof(vis));
int A, B, C;
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (i == j) {
Map[i][j] = 0;
} else {
Map[i][j] = INF;
}
}
}
dis[1] = 0;
for (int i=2; i<=N; ++i) {
dis[i] = INF;
}
for (int i=1; i<=M; ++i) {
cin>>A>>B>>C;
Map[A][B] = Map[B][A] = C;
}
Dijkstra();
cout<<dis[N]<<endl;
}
return 0;
}
void Dijkstra(void)
{
for (int i=2; i<=N; ++i) {
dis[i] = Map[1][i];
}
vis[1] = true;
for (int i=2; i<=N; ++i) {
int Min = INF;
int t;
for (int j=2; j<=N; ++j) {
if (!vis[j] && dis[j]<Min) {
t = j;
Min = dis[j];
}
}
vis[t] = true;
for (int j=2; j<=N; ++j) {
if (!vis[j] && dis[t]+Map[t][j] < dis[j]) {
dis[j] = dis[t] + Map[t][j];
}
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100 + 5;
int N, M;
int Map[maxn][maxn];
void Floyd(void);
int main()
{
// freopen("in.txt", "r", stdin);
while (cin>>N>>M && !(N==0&&M==0)) {
int A, B, C;
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (i == j) {
Map[i][j] = 0;
} else {
Map[i][j] = INF;
}
}
}
for (int i=1; i<=M; ++i) {
cin>>A>>B>>C;
Map[A][B] = Map[B][A] = C;
}
Floyd();
cout<<Map[1][N]<<endl;
}
return 0;
}
void Floyd(void)
{
for (int k=1; k<=N; ++k) {
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (Map[i][k]+Map[k][j] < Map[i][j]) {
Map[i][j] = Map[i][k]+Map[k][j];
}
}
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100 + 5;
int N, M;
int Map[maxn][maxn];
int dis[maxn];
bool vis[maxn];
void SPFA(void);
int main()
{
// freopen("in.txt", "r", stdin);
while (cin>>N>>M && !(N==0&&M==0)) {
int A, B, C;
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (i == j) {
Map[i][j] = 0;
} else {
Map[i][j] = INF;
}
}
}
for (int i=1; i<=M; ++i) {
cin>>A>>B>>C;
Map[A][B] = Map[B][A] = C;
}
SPFA();
cout<<dis[N]<<endl;
}
return 0;
}
void SPFA(void)
{
memset(vis, false, sizeof(vis));
for (int i=1; i<=N; ++i) {
dis[i] = INF;
}
dis[1] = 0;
vis[1] = true;
queue<int> Queue;
Queue.push(1);
while (!Queue.empty()) {
int t = Queue.front();
Queue.pop();
vis[t] = false;
for (int i=1; i<=N; ++i) {
if (dis[i] > dis[t]+Map[t][i]) {
dis[i] = dis[t] + Map[t][i];
if (!vis[i]) {
Queue.push(i);
vis[i] = true;
}
}
}
}
}
题意:
从city 1到city n有很多条路
每条路的载重为这条路中最小载重街道的载重
不管从哪条路走货车的weight都不能超过这条路的载重
为了达到经济效益,要找出载重最大的一条路
解题思路:
dijkstra变形
每次找出到达某个city最大的载重
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1000 + 5;
int Map[maxn][maxn];
int weight[maxn];
bool vis[maxn];
int n, m;
void Dijkstra(void);
int main()
{
// freopen("in.txt", "r", stdin);
int T;
cin>>T;
int scenarios = 0;
while (T--) {
memset(vis, false, sizeof(vis));
++scenarios;
cout<<"Scenario #"<<scenarios<<":"<<endl;
cin>>n>>m;
for (int i=1; i<=n; ++i) {
for (int j=1; j<=n; ++j) {
Map[i][j] = 0;
}
}
int s, e, val;
for (int i=0; i<m; ++i) {
scanf("%d%d%d", &s, &e, &val);
Map[s][e] = Map[e][s] = val;
}
Dijkstra();
cout<<weight[n]<<endl;
cout<<endl;
}
return 0;
}
void Dijkstra(void)
{
weight[1] = 0;
for (int i=2; i<=n; ++i) {
weight[i] = Map[1][i];
}
vis[1] = true;
for (int i=2; i<=n; ++i) {
int t;
int Max = -1;
for (int j=2; j<=n; ++j) {
if (!vis[j] && Max < weight[j]) {
t = j;
Max = weight[j];
}
}
vis[t] = true;
for (int j=2; j<=n; ++j) {
if (!vis[j]) {
Max = weight[t];
if (Max > Map[t][j]) {
Max = Map[t][j];
}
if (weight[j] < Max) {
weight[j] = Max;
}
}
}
}
}
题意:
Mr. M starts from city 1 and his target is city 2
city 1的leader总为1,city 2的leader总为2
And your route should contain at most 1 road which connects two cities of different camp
所以只能从camp1到camp2
不能从camp2到camp1
解题思路:
先建双向路
然后修改为只能从camp1到camp2的单向路,用dijkstra解决
心得:
RE一般就是数组越界或除零,一定要细心去找
注意没有赋初值的变量,它很可能造成数组越界,然后就顺理成章的RE了,而你却无论如何都找不出来
为了保险起见
我以后写 dijkstra 一定要写成下面这样,这是血的教训…
if (Min == INF) {
break;
}
vis[t] = true;
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 600 + 5;
int G[maxn][maxn];
bool vis[maxn];
int dis[maxn];
int N, M;
int leader[maxn];
void Dijkstra(void);
int main()
{
// freopen("in.txt", "r", stdin);
while (scanf("%d", &N) && N != 0) {
memset(vis, false, sizeof(vis));
scanf("%d", &M);
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (i == j) {
G[i][j] = 0;
} else {
G[i][j] = INF;
}
}
}
int A, B, T;
for (int i=0; i<M; ++i) {
scanf("%d%d%d", &A, &B, &T);
G[A][B] = G[B][A] = T;
}
for (int i=1; i<=N; ++i) {
scanf("%d", &leader[i]);
}
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
if (leader[i] == 1 && leader[j] == 2) {
G[j][i] = INF;
}
if (leader[i] == 2 && leader[j] == 1) {
G[i][j] = INF;
}
}
}
Dijkstra();
if (dis[2] != INF) {
printf("%d\n", dis[2]);
} else {
printf("-1\n");
}
}
return 0;
}
void Dijkstra(void)
{
for (int i=2; i<=N; ++i) {
dis[i] = G[1][i];
}
for (int i=1; i<N; ++i) {
int Min = INF;
int t;
for (int j=2; j<=N; ++j) {
if (!vis[j] && dis[j] < Min) {
Min = dis[j];
t = j;
}
}
if (Min == INF) {
break;
}
vis[t] = true;
for (int j=2; j<=N; ++j) {
if (!vis[j] && dis[j] > (dis[t]+G[t][j])) {
dis[j] = dis[t] + G[t][j];
}
}
}
}
Description
很久很久之前,森林里住着一群兔子。有一天,兔子们希望去赏樱花,但当他们到了上野公园门口却忘记了带地图。现在兔子们想求助于你来帮他们找到公园里的最短路。
Input
输入分为三个部分。
第一个部分有P+1行(P<30),第一行为一个整数P,之后的P行表示上野公园的地点。
第二个部分有Q+1行(Q<50),第一行为一个整数Q,之后的Q行每行分别为两个字符串与一个整数,表示这两点有直线的道路,并显示二者之间的矩离(单位为米)。
Output
输出有R行,分别表示每个路线最短的走法。其中两个点之间,用->(矩离)->相隔。
Sample Input
6
Ginza
Sensouji
Shinjukugyoen
Uenokouen
Yoyogikouen
Meijishinguu
6
Ginza Sensouji 80
Shinjukugyoen Sensouji 40
Ginza Uenokouen 35
Uenokouen Shinjukugyoen 85
Sensouji Meijishinguu 60
Meijishinguu Yoyogikouen 35
2
Uenokouen Yoyogikouen
Meijishinguu Meijishinguu
Sample Output
Uenokouen->(35)->Ginza->(80)->Sensouji->(60)->Meijishinguu->(35)->Yoyogikouen
Meijishinguu
题意:
求最短路+打印路径
解题思路:
找到到达每个点的最短路,同时记录使它成为最短路的前一个点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
const int INF = 0x3f3f3f3f;
char s[35][50];
int G[35][35];
char t1[50], t2[50];
bool vis[50];
int dis[50];
int P;
int father[50];
int flag[50];
int Search(char s[]);
void Dijkstra(int a, int b);
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%d", &P);
for (int i=0; i<P; ++i) {
scanf("%s", s[i]);
}
for (int i=0; i<P; ++i) {
for (int j=0; j<P; ++j) {
if (i == j) {
G[i][j] = 0;
} else {
G[i][j] = INF;
}
}
}
int Q;
scanf("%d", &Q);
int n;
for (int i=0; i<Q; ++i) {
scanf("%s%s%d", t1, t2, &n);
int x = Search(t1);
int y = Search(t2);
G[x][y] = G[y][x] = n;
}
int R;
scanf("%d", &R);
for (int i=0; i<R; ++i) {
scanf("%s%s", t1, t2);
int x = Search(t1);
int y = Search(t2);
if (x == y) {
printf("%s\n", s[x]);
} else {
Dijkstra(x, y);
father[x] = x;
int t = y;
int num[50];
int Count = 0;
while (father[t] != t) {
num[Count] = t;
++Count;
t = father[t];
}
num[Count] = x;
printf("%s", s[x]);
for (int j=Count-1; j>=0; --j) {
printf("->(%d)->%s", G[num[j]][num[j+1]], s[num[j]]);
}
printf("\n");
}
}
return 0;
}
int Search(char x[])
{
for (int i=0; i<P; ++i) {
if (strcmp(x, s[i]) == 0) {
return i;
}
}
return 0;
}
void Dijkstra(int a, int b)
{
memset(flag, false, sizeof(flag));
memset(vis, false, sizeof(vis));
vis[a] = true;
for (int i=0; i<P; ++i) {
if (i != a) {
dis[i] = G[a][i];
}
}
for (int i=0; i<P; ++i) {
int Min = INF;
int t;
for (int j=0; j<P; ++j) {
if (!vis[j] && Min > dis[j]) {
Min = dis[j];
t = j;
}
}
vis[t] = true;
if (!flag[t]) {
father[t] = a;
}
if (t == b) {
return;
}
for (int j=0; j<P; ++j) {
if (!vis[j] && dis[j] > dis[t] + G[t][j]) {
dis[j] = dis[t] + G[t][j];
flag[j] = true;
father[j] = t;
}
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
char s[35][50];
int G[35][35];
char t1[50], t2[50];
bool vis[50];
int dis[50][50];
int P;
int father[50][50];
int Search(char s[]);
void Floyd(void);
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%d", &P);
for (int i=0; i<P; ++i) {
scanf("%s", s[i]);
}
for (int i=0; i<P; ++i) {
for (int j=0; j<P; ++j) {
if (i == j) {
G[i][j] = 0;
father[i][j] = -1;
dis[i][j] = 0;
} else {
G[i][j] = INF;
dis[i][j] = INF;
}
}
}
int Q;
scanf("%d", &Q);
int n;
for (int i=0; i<Q; ++i) {
scanf("%s%s%d", t1, t2, &n);
int x = Search(t1);
int y = Search(t2);
G[x][y] = G[y][x] = n;
}
Floyd();
int R;
scanf("%d", &R);
for (int i=0; i<R; ++i) {
scanf("%s%s", t1, t2);
int x = Search(t1);
int y = Search(t2);
if (x == y) {
printf("%s\n", s[x]);
} else {
int num[50];
int Count = 0;
father[x][x] = -1;
while (father[x][y] != -1) {
num[Count] = y;
++Count;
y = father[x][y];
}
num[Count] = x;
printf("%s", s[x]);
for (int j=Count-1; j>=0; --j) {
printf("->(%d)->%s", G[num[j]][num[j+1]], s[num[j]]);
}
printf("\n");
}
}
return 0;
}
int Search(char x[])
{
for (int i=0; i<P; ++i) {
if (strcmp(x, s[i]) == 0) {
return i;
}
}
return 0;
}
void Floyd(void)
{
for (int k=0; k<P; ++k) {
memset(vis, false, sizeof(vis));
for (int i=0; i<P; ++i) {
int Min = INF;
int t;
for (int j=0; j<P; ++j) {
if (!vis[j] && dis[k][j] < Min) {
Min = dis[k][j];
t = j;
}
}
if (Min == INF) {
break;
}
vis[t] = true;
for (int j=0; j<P; ++j) {
if (!vis[j] && dis[k][t] + G[t][j] < dis[k][j]) {
dis[k][j] = dis[k][t] + G[t][j];
father[k][j] = t;
}
}
}
}
}
题意:
farms comprises N (1 ≤ N ≤ 500) fields
有M条路,路的一端为S,另一端为E,从S到E和从E到S花费的时间都为T
又有W条路,起点为虫洞S,终点为E,穿越回去花费的时间为T
he wants to do the following:
start at some field,
travel through some paths and wormholes,
and return to the starting field a time before his initial departure.
Perhaps he will be able to meet himself :)
解题思路:
用Bellman-Ford算法找一下有没有负权环
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Edge {
int x, y;
int val;
};
const int INF = 10000 + 5;
const int maxn = 500 + 5;
int dis[maxn];
int Count;
int N, M, W;
Edge edge[6000];
int Bellman_Ford(void);
int main()
{
// freopen("in.txt", "r", stdin);
int F;
while (cin>>F) {
while (F--) {
Count = 0;
cin>>N>>M>>W;
int S, E, T;
for (int i=0; i<M; ++i) {
cin>>S>>E>>T;
edge[Count].x = S;
edge[Count].y = E;
edge[Count].val = T;
++Count;
edge[Count].x = E;
edge[Count].y = S;
edge[Count].val = T;
++Count;
}
for (int i=0; i<W; ++i) {
cin>>S>>E>>T;
edge[Count].x = S;
edge[Count].y = E;
edge[Count].val = -T;
++Count;
}
if (Bellman_Ford()) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
}
return 0;
}
int Bellman_Ford(void)
{
for (int i=1; i<=N; ++i) {
dis[i] = INF;
}
int flag;
for (int i=0; i<N-1; ++i) {
flag = 0;
for (int j=0; j<Count; ++j) {
if (dis[edge[j].y] > dis[edge[j].x] + edge[j].val) {
dis[edge[j].y] = dis[edge[j].x] + edge[j].val;
flag = 1;
}
}
if (flag == 0) {
break;
}
}
for (int i=0; i<Count; ++i) {
if (dis[edge[i].y] > dis[edge[i].x] + edge[i].val) {
return 1;
}
}
return 0;
}