本题本来是练习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);
}
声明两个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]);
}