训练的题目
最短路变形
题意:这个题意,太长了,总结回来只有两三句话。输入n表示n个点,从0到n-1,输入m表示m条无向边,输入t,表示终点。要你求起点0到终点t的最短路,不过要先满足一个条件,就是路径的点数不超过10个(包括起点和终点在内 <= 10),如果在10个点内娶不到或者图根本不连通,那么输出no,否则输出最短路
又是一个加了限制的最短路,是要先满足10个点以内再求最短路的,训练的时候就是看错了一直WA。
这题和 poj 1724 ROADS 是一样的题目。可以看作每条边的花费是1点数,你从0出发,手上有9点数,在点数够用的情况下走到终点t的最短路
因此仿照poj这题的代码,写了一个dp,就过了,再仿照写了个bfs搜索,也过了 , 在仿照写了个优先队列+dij , 得到一个MLE,这个是为什么?其实还没想清楚,应该是入队的元素太多(没有加以限制)导致爆了空间,poj那题是100个点,给了64m,这题是1000个点,给了32m,应该是这样了
后来上网找到了唯一一个代码,作者的代码写得比我好啊,简单,易懂,附上地址
http://soj.me/viewsource.php?sid=1796545
1.dp的代码
#include <cstdio> #include <cstring> #include <vector> using namespace std; #define N 1010 #define INF 0x3f3f3f3f const int lim = 9; typedef pair<int,int>pii; vector<pii>e[N]; int d[N][15]; void dfs(int u , int c) { if(d[u][c] != -1) return ; d[u][c] = INF; int size = e[u].size(); for(int i=0; i<size; i++) { pii temp = e[u][i]; int v = temp.first; int w = temp.second; if(c-1 >= 0) { dfs(v,c-1); if(d[v][c-1] + w < d[u][c]) d[u][c] = d[v][c-1] + w; } } } int main() { int n,m,t; while(scanf("%d%d%d",&n,&m,&t)!=EOF && n) { for(int i=0; i<n; i++) e[i].clear(); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); e[u].push_back( make_pair(v,w) ); e[v].push_back( make_pair(u,w) ); } memset(d,-1,sizeof(d)); for(int i=0; i<=lim; i++) d[0][i] = 0; int res = INF; for(int i=0; i<=lim; i++) { dfs(t,i); if(d[t][i] < res) res = d[t][i]; } if(res == INF) printf("no\n"); else printf("%d\n",res); } return 0; }
2.bfs搜索,彻底搜索更新所有状态
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; #define N 1010 #define INF 0x3f3f3f3f const int lim = 9; typedef pair<int,int>pii; vector<pii>e[N]; int d[N][15]; void bfs(int s , int t) { bool inq[N]; queue<int>q; while(!q.empty()) q.pop(); memset(inq,false,sizeof(inq)); memset(d,0x3f,sizeof(d)); for(int i=0; i<=lim; i++) d[s][i]=0; inq[s] = true; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); inq[u] = false; int size = e[u].size(); for(int i=0; i<size; i++) { pii temp = e[u][i]; int v = temp.first; int w = temp.second; int c = 1; for(int j=1; j<=lim; j++) if(d[u][j-c] + w < d[v][j]) { d[v][j] = d[u][j-c] + w; if(!inq[v]) { inq[v] = true; q.push(v); } } } } int res = INF; for(int i=0; i<=lim; i++) if(d[t][i] < res) res = d[t][i]; if(res == INF) printf("no\n"); else printf("%d\n",res); } int main() { int n,m,t; while(scanf("%d%d%d",&n,&m,&t)!=EOF && n) { for(int i=0; i<n; i++) e[i].clear(); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); e[u].push_back( make_pair(v,w) ); e[v].push_back( make_pair(u,w) ); } bfs(0,t); } }
3.网上找到的代码
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; #define N 1010 #define INF 0x3f3f3f3f const int lim = 9; typedef pair<int,int>pii; vector<pii>e[N]; int d[N]; int len[N]; void bfs(int s , int t) { bool inq[N]; queue<int>q; while(!q.empty()) q.pop(); memset(inq,false,sizeof(inq)); memset(d,0x3f,sizeof(d)); memset(len,0,sizeof(len)); d[s] = 0; inq[s] = true; q.push(s); while(!q.empty()) { int u =q.front(); q.pop(); inq[u] = false; int size = e[u].size(); for(int i=0; i<size; i++) { pii temp = e[u][i]; int v = temp.first; int w = temp.second; int c = 1; if(d[u] + w < d[v]) { d[v] = d[u] + w; len[v] = len[u] + c; if(len[v] <= lim) q.push(v); } } } if(d[t] == INF) printf("no\n"); else printf("%d\n",d[t]); } int main() { int n,m,t; while(scanf("%d%d%d",&n,&m,&t)!=EOF && n) { for(int i=0; i<n; i++) e[i].clear(); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); e[u].push_back( make_pair(v,w) ); e[v].push_back( make_pair(u,w) ); } bfs(0,t); } }