AtCoder Beginner Contest 164 E(二维 图上dp)

题目链接

E - Two Currencies

题意:给你n节点m条边的无向图

每条边有s 和 t ,s 代表 经过这条路要花费s银币,t代表走这条路需要消耗的时间

每个节点有c[i]、d[i] 代表在i这个节点兑换c个银币消耗d时间。

问从1节点出发  到达其他节点时的最小时间 

初始金币为s

做法:设dp[i][j] 代表 到达i这个节点拥有j银币时的最小时间。

进行n+1轮的图上dp即可。

注意要先枚举被到达的节点i  再枚举从起始点v->i 的dp转移。

如果是枚举i  ->v 会wa在倒数第二个点。原因不详。。

要从v的父亲转移过来,不能从v往外辐射,不知道是不是我代码问题 会wa在倒数第二个点

#include
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const ll inf=0x3f3f3f3f;
const int N=100;
struct edge
{
    int v;
    ll s,t;
    int ne;
}e[N<<1];
int n,m,cnt,head[N];
ll s,dis[N],c[N],d[N],dp[N][3000];

void add(int u,int v,ll w,ll t)
{
    e[++cnt]={v,w,t,head[u]};
    head[u]=cnt;
    e[++cnt]={u,w,t,head[v]};
    head[v]=cnt;
}

void bfs()
{
    if(s>=2500) s=2500;
    dp[1][s]=0;
    for(int up=1;up<=n+2;++up){
        for(int i=1;i<=n;++i){
            for(int j=head[i];j;j=e[j].ne){
                for(int now=0;now<=2500;++now){
                    if(now+e[j].s>=0){
                        dp[i][now]=min(dp[i][now],dp[e[j].v][now+e[j].s]+e[j].t);

                //dp[e[j].v][now-e[j].s]=min(dp[e[j].v][now-e[j].s],dp[i][now]+e[j].t);
                //这样wa
               
                    }
                }
            }


            for(int now=0;now<=2500;now++){
                if(now-c[i]>=0){
                    dp[i][now]=min(dp[i][now-c[i]]+d[i],dp[i][now]);
                }
            }
        }
    }
}
void solve()
{
   cin>>n>>m>>s;
   mem(dp,inf);
   rep(i,1,m)
   {
       int u,v;ll a,b;
       cin>>u>>v>>a>>b;
       add(u,v,a,b);
   }
   rep(i,1,n) cin>>c[i]>>d[i];
   bfs();
   for(int i=2;i<=n;++i){
        ll ans=1e18;
        for(int now=0;now<=2500;++now) ans=min(ans,dp[i][now]);
        printf("%lld\n",ans);
   }
}
int main()
{
	solve();
}

 

你可能感兴趣的:(AtCode题解)