本题本来是练习SPFA的。我一看DIscuss能用裸搜。果断敲了一个前向星+DFS,居然超时了。后来发现是Next数组开小了,应该开成两倍边数的大小。
后来我又把前向星改成邻接表,也AC了。。最后写一发SPFA。
前向星+DFS+剪枝:(AC):
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <vector> #include <queue> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define Maxn 5005 #define Maxm 40005<<1 struct Edge { int x; int y; int c; int d; }; Edge e[Maxm]; int first[Maxn]; int next[Maxm];//注意不要写成next[Maxn],切记 int used[Maxn]; int k; int s,t; int n,m; int mma = INF; void dfs(int start,int total_len,int total_k) { //加两个剪支,体力值超过范围或者长度必然不是最优两种情况 if(total_k > k || total_len > mma) { return; } if(start == t) { if(total_k<=k) { mma = mma>total_len ? total_len : mma; } return; } used[start] = 1; for(int i=first[start]; i!=-1; i=next[i]) { if(used[e[i].y] == 0) { dfs(e[i].y,total_len + e[i].d ,total_k + e[i].c); } } used[start] = 0; } int main() { /*#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif*/ scanf(" %d %d",&n,&m); memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); memset(used,0,sizeof(used)); int temp = m; int i = 0; while(temp--) { scanf(" %d %d %d %d",&e[i].x,&e[i].y,&e[i].c,&e[i].d); next[i] = first[e[i].x]; first[e[i].x] = i; i++; e[i].x = e[i-1].y,e[i].y = e[i-1].x,e[i].c = e[i-1].c,e[i].d = e[i-1].d; next[i] = first[e[i].x]; first[e[i].x] = i; i++; } scanf(" %d %d %d",&s,&t,&k); dfs(s,0,0); if(mma == INF) printf("-1\n"); else printf("%d\n",mma); }
邻接表+DFS+剪枝(AC):
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <vector> #include <queue> #include <algorithm> using namespace std; #define INF 0xffffff #define Maxn 5005 #define Maxm 40005<<1 struct vertex { int n; int length; int cost; }; vector < vertex > graph[Maxn]; int used[Maxn]; int k; int s,t; int n,m; int mma = INF; void dfs(int start,int total_len,int total_k) { //加两个剪支,体力值超过范围或者长度必然不是最优两种情况 if(total_k <=k && total_len < mma) { if(start == t) { mma = total_len; } else { used[start] = 1; for(int i=0; i<graph[start].size(); i++) { if(used[graph[start][i].n] == 0) { dfs(graph[start][i].n,total_len + graph[start][i].length,total_k + graph[start][i].cost); } } used[start] = 0; } } } int main() { /*#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif*/ int st,vd,ct,le; scanf(" %d %d",&n,&m); memset(used,0,sizeof(used)); int temp = m; int i = 0; while(temp--) { scanf(" %d %d %d %d",&st,&vd,&ct,&le); vertex one; one.n = vd; one.length = le; one.cost = ct; graph[st].push_back(one); vertex other; other.n = st; other.cost = ct; other.length = le; graph[vd].push_back(other); } scanf(" %d %d %d",&s,&t,&k); dfs(s,0,0); if(mma == INF) printf("-1\n"); else printf("%d\n",mma); }
前向星+SPFA (AC):
声明两个Dist数组,一个代表时间(距离),一个代表体力值,只有两个Dist同时满足条件时,才会更新,也才有机会入队列。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <vector> #include <queue> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define Maxn 5005 #define Maxm 40005<<1 struct Edge { int x; int y; int c; int d; }; Edge e[Maxm]; int first[Maxn]; int next[Maxm]; int used[Maxn]; int distC[Maxn];//体力 int distD[Maxn];//时间 int k; int s,t; int n,m; void spfa(int s) { queue<int> q; memset(used,0,sizeof(used)); used[s] = 1; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); used[u] = 0; for(int i=first[u]; i!=-1; i=next[i]) { int v = e[i].y; int c = e[i].c; int d = e[i].d; if(distD[v] - d > distD[u] && distC[u] + c <=k) { distD[v] = distD[u] + d; distC[v] = distC[u] + c; if(used[v] == 0) { used[v] = 1; q.push(v); } } } } } int main() { /*#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif*/ scanf(" %d %d",&n,&m); memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); memset(used,0,sizeof(used)); memset(distC,0x3f,sizeof(distC)); memset(distD,0x3f,sizeof(distD)); int temp = m; int i = 0; while(temp--) { scanf(" %d %d %d %d",&e[i].x,&e[i].y,&e[i].c,&e[i].d); next[i] = first[e[i].x]; first[e[i].x] = i; i++; e[i].x = e[i-1].y,e[i].y = e[i-1].x,e[i].c = e[i-1].c,e[i].d = e[i-1].d; next[i] = first[e[i].x]; first[e[i].x] = i; i++; } scanf(" %d %d %d",&s,&t,&k); distD[s] = distC[s] = 0; spfa(s); if(distD[t] == INF) printf("-1\n"); else printf("%d\n",distD[t]); }