方法: SPFA
解析:
好题,想挺久没想出来。
主要卡在什么地方呢?
如何在一维已知的时候搞第二维呢?
没想到这个最短路怎么传。
其实小范围的话我们不妨把一维扔到数组的一维。
也就是我们定义一个二维数组f[i][j]代表到第i个点,第一维费用为j时的最小第二维费用。
这里spfa有一个判断的问题,就是bfs什么时候停止?
因为题中说了费用不超过一百,所以如果我们跑出费用比(n-1)*100还要大,那显然停止了。
极限情况即一条链。
所以这么搞的话我们从某种程度上来说使一维单调。
并且可以在枚举一维的同时判断第二维的值是否合法。
代码:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 110
#define M 310
#define INF 0x3f3f3f3f
using namespace std;
int n,m,s,t,cnt;
int head[N];
struct node
{
int from,to,v1,v2,next;
}edge[M<<1];
struct ele
{
int no,val;
};
int f[N][N*N];
int v[N][N*N];
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void edgeadd(int from,int to,int v1,int v2)
{
edge[cnt].from=from,edge[cnt].to=to,edge[cnt].v1=v1,edge[cnt].v2=v2;
edge[cnt].next=head[from];
head[from]=cnt++;
}
void spfa()
{
memset(f,0x3f,sizeof(f));
queue<ele>q;
ele fir;
fir.no=s,fir.val=0;
q.push(fir);
v[fir.no][fir.val]=1;
f[fir.no][fir.val]=0;
while(!q.empty())
{
ele u=q.front();
q.pop();
v[u.no][u.val]=0;
if(u.val>n*N-n)continue;
for(int i=head[u.no];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(f[u.no][u.val]+edge[i].v2<f[to][u.val+edge[i].v1])
{
f[to][u.val+edge[i].v1]=f[u.no][u.val]+edge[i].v2;
if(!v[to][u.val+edge[i].v1])
{
v[to][u.val+edge[i].v1]=1;
ele tmp;
tmp.no=to,tmp.val=u.val+edge[i].v1;
q.push(tmp);
}
}
}
}
}
int main()
{
init();
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++)
{
int x,y,v1,v2;
scanf("%d%d%d%d",&x,&y,&v1,&v2);
edgeadd(x,y,v1,v2),edgeadd(y,x,v1,v2);
}
spfa();
int mi=INF;
int ans=0;
for(int i=0;i<=n*N-n;i++)
{
if(f[t][i]==INF)continue;
if(f[t][i]>=mi)continue;
mi=f[t][i];
ans++;
}
printf("%d\n",ans);
}