最短路dijkstra入门题
HDU 1874 畅通工程续
水dijkstra
View Code
#include<stdio.h> #include<string.h> #define INF 1000000 #define maxn 201 int adj[maxn][maxn],dis[maxn];//pre[maxn] bool vis[maxn]; int n ,m; int dijkstra(int src, int dest) { int i ,j, k, u, min; for(i=0;i<n;i++) { vis[i]=0; dis[i]=adj[src][i]; //if(src != i && dis[src] < INF)pre[i] = src; //else pre[i] = -1; } vis[src]=1;dis[src]=0; for(i=0;i<n;i++) { min = INF; for(j=0;j<n;j++) { if(!vis[j]&&min > dis[j]) { min = dis[j]; u = j; //pre[j] = src; } } vis[u]=1; for(j=0;j<n;j++) { if(!vis[j] && dis[u] + adj[u][j] < dis[j]&&adj[u][j]!=INF) { dis[j] = dis[u] + adj[u][j]; //pre[j] = u; } } } return dis[dest] < INF? dis[dest]: -1; } void init() { int i ,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(i==j)adj[i][j]=0; else adj[i][j]=INF; } } } int main() { int x, y ,w; while(~scanf("%d%d",&n,&m)&&n) { init(); while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[x][y] > w) { adj[x][y]=w; adj[y][x]=w; } } int s,t; scanf("%d%d",&s,&t); printf("%d\n",dijkstra(s,t)); } return 0; }
HDU 2112 HDU Today
字符串处理,可以人工处理,也可以用STL中的map,个人觉得人工处理不麻烦,map麻烦死了,就自己处理了
然后 dijkstra水一个
View Code
#include<stdio.h> #include<string.h> #define INF 1000000 #define maxn 201 int adj[maxn][maxn],dis[maxn];//pre[maxn] bool vis[maxn]; int n ,m; int dijkstra(int src, int dest) { int i ,j, k, u, min; for(i=0;i<n;i++) { vis[i]=0; dis[i]=adj[src][i]; //if(src != i && dis[src] < INF)pre[i] = src; //else pre[i] = -1; } vis[src]=1;dis[src]=0; for(i=0;i<n;i++) { min = INF; for(j=0;j<n;j++) { if(!vis[j]&&min > dis[j]) { min = dis[j]; u = j; //pre[j] = src; } } vis[u]=1; for(j=0;j<n;j++) { if(!vis[j] && dis[u] + adj[u][j] < dis[j]&&adj[u][j]!=INF) { dis[j] = dis[u] + adj[u][j]; //pre[j] = u; } } } return dis[dest] < INF? dis[dest]: -1; } void init() { int i ,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(i==j)adj[i][j]=0; else adj[i][j]=INF; } } } int main() { int x, y ,w; while(~scanf("%d%d",&n,&m)&&n) { init(); while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[x][y] > w) { adj[x][y]=w; adj[y][x]=w; } } int s,t; scanf("%d%d",&s,&t); printf("%d\n",dijkstra(s,t)); } return 0; }
HDU 2680 Choose the best route
是单向图WA了好几次才发现;
题目起点有好几个,终点就一个;
方法一:题目顶点1,2,3......n,自己设置个0顶点作为源点,让0点与所有起点连接,权值为0,即adj[0][起点]=0,别忘了初始化adj时把0也初始化;
View Code
#include<stdio.h> #include<string.h> #define maxn 1001 #define INF 100000000 int dis[maxn],adj[maxn][maxn]; bool vis[maxn]; int n, m, s, t; void dijkstra(int v) { int i, j, k, min, u; for(i=1;i<=n;i++) { dis[i]=adj[v][i]; vis[i]=0; } vis[v]=1;dis[v]=0; for(i=1;i<=n;i++) { min = INF; for(j=1;j<=n;j++) { if(min > dis[j]&&!vis[j]) { min = dis[j]; u = j; } } if(min == INF)break; vis[u]=1; for(j=1;j<=n;j++) { if(dis[u] + adj[u][j] < dis[j]&&!vis[j]) { dis[j] = dis[u] + adj[u][j]; } } } } int main() { int i, j, x, y, w; while(~scanf("%d%d%d",&n,&m,&t)) { for(i=0;i<=n;i++) for(j=0;j<=n;j++) adj[i][j]=INF; while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[x][y] > w)adj[x][y] = w; } scanf("%d",&m); while(m--) { scanf("%d",&x); adj[0][x]=0; } dijkstra(0); if(dis[t]== INF)printf("-1\n"); else printf("%d\n",dis[t]); } return 0; }
方法二:把终点作为源点写个逆向的dijkstra
可以读入边时就反 一下
View Code
#include<stdio.h> #include<string.h> #define maxn 1001 #define INF 100000000 int dis[maxn],adj[maxn][maxn]; bool vis[maxn]; int n, m, s, t; void dijkstra(int v) { int i, j, k, min, u; for(i=1;i<=n;i++) { dis[i]=adj[v][i]; vis[i]=0; } vis[v]=1;dis[v]=0; for(i=1;i<=n;i++) { min = INF; for(j=1;j<=n;j++) { if(min > dis[j]&&!vis[j]) { min = dis[j]; u = j; } } if(min == INF)break; vis[u]=1; for(j=1;j<=n;j++) { if(dis[u] + adj[u][j] < dis[j]&&!vis[j]) { dis[j] = dis[u] + adj[u][j]; } } } } int main() { int i, j, x, y, w; while(~scanf("%d%d%d",&n,&m,&t)) { for(i=0;i<=n;i++) for(j=0;j<=n;j++) adj[i][j]=INF; while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[y][x] > w)adj[y][x] = w; //注意反了 } scanf("%d",&m); int ans = INF; dijkstra(t); while(m--) { scanf("%d",&x); if(dis[x]< ans)ans=dis[x]; } if(ans== INF)printf("-1\n"); else printf("%d\n",ans); } return 0; }
也可以在dijkstra里面反一下
View Code
#include<stdio.h> #include<string.h> #define maxn 1001 #define INF 100000000 int dis[maxn],adj[maxn][maxn]; bool vis[maxn]; int n, m, s, t; void dijkstra(int v) { int i, j, k, min, u; for(i=1;i<=n;i++) { dis[i]=adj[i][v]; //注意adj下标反了 vis[i]=0; } vis[v]=1;dis[v]=0; for(i=1;i<=n;i++) { min = INF; for(j=1;j<=n;j++) { if(min > dis[j]&&!vis[j]) { min = dis[j]; u = j; } } if(min == INF)break; vis[u]=1; for(j=1;j<=n;j++) { if(dis[u] + adj[j][u] < dis[j]&&!vis[j]) //注意adj下标反了 { dis[j] = dis[u] + adj[j][u]; //注意adj下标反了 } } } } int main() { int i, j, x, y, w; while(~scanf("%d%d%d",&n,&m,&t)) { for(i=0;i<=n;i++) for(j=0;j<=n;j++) adj[i][j]=INF; while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[x][y] > w)adj[x][y] = w; } scanf("%d",&m); int ans = INF; dijkstra(t); while(m--) { scanf("%d",&x); if(dis[x]< ans)ans=dis[x]; } if(ans== INF)printf("-1\n"); else printf("%d\n",ans); } return 0; }
HDU 2066 一个人的旅行
这题终点起点都有多个,可以用上一题的方法一,设置虚拟起点0和虚拟终点1001
View Code
#include<stdio.h> #include<string.h> #define maxn 1003 #define INF 100000000 int n, m; bool vis[maxn]; int adj[maxn][maxn],dis[maxn],pre[maxn]; int dijstra(int scr, int dest) { int i ,j, k, u; for(i=1;i<=n;i++) { vis[i]=0; dis[i]=adj[scr][i]; } vis[scr]=1;dis[scr]=0; for(i=1;i<n;i++) { int min = INF; for(j=1;j<=n;j++) { if(min > dis[j]&&!vis[j]) { min = dis[j]; u=j; } } if(min==INF)break; vis[u]=1; for(j=1;j<=n;j++) { if(dis[u]+adj[u][j] < dis[j]&&!vis[j]) { dis[j] = dis[u] + adj[u][j]; } } } return dis[dest] < INF ? dis[dest] : -1; } int main() { int x, y, w, i, j, s, t, p, q; while(~scanf("%d%d%d",&m,&p,&q)) { n=1001; for(i=0;i<=n+2;i++) { for(j=0;j<=n+2;j++) { adj[i][j]=INF; } } while(m--) { scanf("%d%d%d",&x,&y,&w); if(adj[x][y] > w) { adj[x][y]=w; adj[y][x]=w; } } while(p--) { scanf("%d",&s); adj[0][s]=0; } while(q--) { scanf("%d",&t); adj[t][1001]=0; } printf("%d\n",dijstra(0, 1001)); } return 0; }
POJ 2240 Arbitrage
floyd水题
View Code
#include<stdio.h> #include<string.h> using namespace std; int n, m; double adj[32][32]; char str[32][101]; char s[101]; int find(char s[]) { int i; for(i=1;i<=n;i++) if(strcmp(s,str[i])==0)return i; } int floyd() { int i,j,k; for(k=1;k<=n;k++) { for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(adj[i][j]<adj[i][k]*adj[k][j]) adj[i][j]=adj[i][k]*adj[k][j]; if(adj[1][1]>1)return 1; } } } return 0; } int main() { int i, j, x, y, X=1; double w; while(~scanf("%d",&n)&&n) { for(i=1;i<=n;i++) scanf("%s",str[i]); memset(adj,0,sizeof(adj)); scanf("%d",&m); while(m--) { scanf("%s",s);x=find(s); scanf("%lf",&w); scanf("%s",s);y=find(s); adj[x][y]=w; } printf("Case %d: ",X++); floyd()?puts("Yes"):puts("No"); } return 0; }