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;
}

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