PAT 1018. Public Bike Management (30) (最短路+DFS)

传送门

题意:

    从0号点到给定的有问题的点en,要保证每个点自行车数量为Cmax的一半,一个点的自行车数量可以被这条路径上前几个点多的自行车来补. 问你从0到问题点en的最短路径,如果最短路径相同,输出需要从0点携带的自行车数量最小的路径,如果还相同输出该路径上需要带回去最少的路径。(需要将路径上经过的所有点的自行车数量都变为完美的)

思路:

    如果单纯的路径最短,或者带出来的自行车数量最小还可以用最短路算法贪心的做,现在要同时维护三个好像不太好处理了,对于这个题目我们先用最短路求出0到问题点en的最短路径,然后从0点开始dfs暴力找到所有等于最短路径的路径(这个过程记录下路径),然后判断一下哪个最优就行了.(也可以直接爆搜,维护最短路径)

#include<bits/stdc++.h>
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;

const int maxn = 5e2+5;
struct node
{
    int to,cost;
    node(int x = 0,int y = 0)
    {
        to = x,cost = y;
    }
};
int cm,n,m,en;
vector<node>vt[maxn];
int val[maxn],vis[maxn];
int dis[maxn];
int m_send,m_take_back;
vector<int>ans,path;
void dij(int st,int dt)
{
    for(int i = 0;i <= n;++i)
    {
        dis[i] = inf;
        vis[i] = 0;
    }
    dis[st] = 0;
    queue<int>Q;
    while(!Q.empty()) Q.pop();
    Q.push(st);
    vis[st] = 1;
    while(!Q.empty())
    {
        int cur = Q.front();Q.pop();
        vis[cur] = 0;
        for(int i = 0;i < vt[cur].size();++i)
        {
            int to = vt[cur][i].to;
            int cost = vt[cur][i].cost;
            if(dis[to] > dis[cur] + cost)
            {
                dis[to] = dis[cur] + cost;
                if(!vis[to])
                {
                    Q.push(to),vis[to] = 1;
                }
            }
        }
    }
    return ;
}
bool book[maxn];
void dfs(int cur,int s)
{
    if(s > dis[en]) return ;
    if(cur == en)
    {
        int need = 0,take_back = 0;
        if(s == dis[en])
        {
            for(int i = 0;i < path.size();++i)
            {
                if(val[path[i]] > 0)
                    take_back += val[path[i]];
                else
                {
                    if(take_back > 0)
                    {
                        if(take_back >= abs(val[path[i]]))
                            take_back -= abs(val[path[i]]);
                        else
                        {
                            need += abs(val[path[i]]) - take_back;
                            take_back = 0;
                        }
                    }
                    else
                        need += abs(val[path[i]]);
                }
            }
        }
        if(need < m_send)
        {
            m_send = need;
            m_take_back = take_back;
            ans = path;
        }
        else if(need == m_send && take_back < m_take_back)
        {
            m_send = need;
            m_take_back = take_back;
            ans = path;
        }
    }
    for(int i = 0;i < vt[cur].size();++i)
    {
        int v = vt[cur][i].to;
        int cost = vt[cur][i].cost;
        if(!vis[v])
        {
            vis[v] = 1;
            path.pb(v);
            dfs(v,s + cost);
            vis[v] = 0;
            path.pop_back();
        }
    }
    return ;
}
int main()
{
    while(~scanf("%d %d %d %d",&cm,&n,&en,&m))
    {
        cm /= 2;
        for(int i = 0;i <= n;++i)
            vt[i].clear();
        for(int i = 1;i <= n;++i)
            scanf("%d",&val[i]),val[i] -= cm;
            val[0] = 0;
        for(int i = 0;i < m;++i)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            vt[a].pb(node(b,c));
            vt[b].pb(node(a,c));
        }
        dij(0,en);
        m_send = m_take_back = inf;
        ans.clear();
        path.clear();
        memset(book,0,sizeof book);
        path.pb(0);
        book[0] = 1;
        dfs(0,0);
        printf("%d ",m_send);
        for(int i = 0;i < ans.size();++i)
        {
            if(i == 0) printf("0");
            else
                printf("->%d",ans[i]);
        }
        printf(" %d\n",m_take_back);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章