BZOJ--1266: [AHOI2006]上學路線route--最短路+網絡流

1266: [AHOI2006]上學路線route

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 2766  Solved: 1037
[Submit][Status][Discuss]

Description

可可和卡卡家住合肥市的東郊,每天上學他們都要轉車多次才能到達市區西端的學校。直到有一天他們兩人蔘加了學校的信息學奧林匹克競賽小組才發現每天上學的乘車路線不一定是最優的。 可可:“很可能我們在上學的路途上浪費了大量的時間,讓我們寫一個程序來計算上學需要的最少時間吧!” 合肥市一共設有N個公交車站,不妨將它們編號爲1…N的自然數,並認爲可可和卡卡家住在1號汽車站附近,而他們學校在N號汽車站。市內有M條直達汽車路線,執行第i條路線的公交車往返於站點pi和qi之間,從起點到終點需要花費的時間爲ti。(1<=i<=M, 1<=pi, qi<=N) 兩個人坐在電腦前,根據上面的信息很快就編程算出了最優的乘車方案。然而可可忽然有了一個鬼點子,他想趁卡卡不備,在卡卡的輸入數據中刪去一些路線,從而讓卡卡的程序得出的答案大於實際的最短時間。而對於每一條路線i事實上都有一個代價ci:刪去路線的ci越大卡卡就越容易發現這個玩笑,可可想知道什麼樣的刪除方案可以達到他的目的而讓被刪除的公交車路線ci之和最小。 [任務] 編寫一個程序:  從輸入文件中讀取合肥市公交路線的信息;  計算出實際上可可和卡卡上學需要花費的最少時間;  幫助可可設計一個方案,刪除輸入信息中的一些公交路線,使得刪除後從家到學校需要的最少時間變大,而被刪除路線的ci和最小;向輸出文件輸出答案。

Input

輸入文件中第一行有兩個正整數N和M,分別表示合肥市公交車站和公交汽車路線的個數。以下M行,每行(第i行,總第(i+1)行)用四個正整數描述第i條路線:pi, qi, ti, ci;具體含義見上文描述。

Output

輸出文件最多有兩行。 第一行中僅有一個整數,表示從可可和卡卡家到學校需要的最短時間。 第二行輸出一個整數C,表示Ci之和

Sample Input

6 7
1 2 1 3
2 6 1 5
1 3 1 1
3 4 1 1
4 6 1 1
5 6 1 2
1 5 1 4

Sample Output

2
5
 

HINT

2<=N<=500, 1<=M<=124 750, 1<=ti, ci<=10 000
合肥市的公交網絡十分發達,你可以認爲任意兩個車站間都可以通過直達或轉車互相到達,當然如果在你提供的刪除方案中,家和學校無法互相到達,那麼則認爲上學需要的最短爲正無窮大:這顯然是一個合法的方案。

Source

一模一樣的題---https://blog.csdn.net/lanshan1111/article/details/100935227

/**************************************************************
    Problem: 1266
    User: pre111
    Language: C++
    Result: Accepted
    Time:304 ms
    Memory:9100 kb
****************************************************************/
 
#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>      //STL雙端隊列容器
#include <exception>    //異常處理類
#include <fstream>
#include <functional>   //STL定義運算函數(代替運算符)
#include <limits>
#include <list>      //STL線性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本輸入/輸出支持
#include<iosfwd>     //輸入/輸出系統使用的前置聲明
#include <iostream>
#include <istream>     //基本輸入流
#include <ostream>     //基本輸出流
#include <queue>      //STL隊列容器
#include <set>       //STL 集合容器
#include <sstream>    //基於字符串的流
#include <stack>      //STL堆棧容器    
#include <string>     //字符串類
#include <vector>     //STL動態數組容器
#define ll long long
using namespace std;
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn = 500 + 5;
const int maxm=2*124750+5;
typedef pair<int, int> P;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, cas;
 
int d[maxm];
struct GDJ
{
    int head[maxn], cnt;
    int to[maxm], nxt[maxm];
    int val[maxm];
    int va[maxm];
    void init()
    {
        memset(head, -1, (n + 5) * sizeof(int));
        memset(va,0,(n + 5) * sizeof(int));
        cnt = -1;
    }
 
    void ade(int a, int b, int c,int d)
    {
        to[++cnt] = b;
        nxt[cnt] = head[a];
        val[cnt] = c;
        va[cnt]=d;
        head[a] = cnt;
    }
 
    bool vis[maxn];
    void dj(int s)
    {
        priority_queue<P, vector<P>, greater<P> > que;
        memset(d, 0x3f, (n + 5) * sizeof(int));
        memset(vis, 0, (n + 5) * sizeof(bool));
        d[s] = 0;
        que.push(P(0, s));
        while(!que.empty())
        {
            P p = que.top();
            que.pop();
            int u = p.second;
            if(vis[u])
                continue;
            vis[u] = 1;
            for(int i = head[u]; ~i; i = nxt[i])
            {
                int v = to[i];
                if(d[v] > d[u] + val[i])
                {
                    d[v] = d[u] + val[i];
                    que.push(P(d[v], v));
                }
            }
        }
    }
} DJ;
 
struct GDC
{
    int depth[maxn], cur[maxn], head[maxn], cnt;
    int to[maxm], nxt[maxm];
    int val[maxm];
 
    void init()
    {
        memset(head, -1, (n + 5) * sizeof(int));
        cnt = -1;
    }
 
    void ade(int a, int b, int c)
    {
        to[++cnt] = b;
        nxt[cnt] = head[a];
        val[cnt] = c;
        head[a] = cnt;
    }
 
    bool bfs()
    {
        queue<int> que;
        que.push(1);
        memset(depth, 0, (n + 5) * sizeof(int));
        depth[1] = 1;
        while(!que.empty())
        {
            int u = que.front();
            que.pop();
            for(int i = head[u]; ~i; i = nxt[i])
            {
                if(val[i] > 0 && depth[to[i]] == 0)
                {
                    depth[to[i]] = depth[u] + 1;
                    que.push(to[i]);
                }
            }
        }
        if(depth[n])
            return 1;
        else
            return 0;
    }
 
    int dfs(int u, int dist)
    {
        if(u == n)
            return dist;
        for(int &i = cur[u]; ~i; i = nxt[i])
        {
            if(depth[to[i]] == depth[u] + 1 && val[i] > 0)
            {
                int tmp = dfs(to[i], min(dist, val[i]));
                //cout<<tmp<<"---"<<endl;
                if(tmp > 0)
                {
                    val[i] -= tmp;
                    val[i ^ 1] += tmp;
                    return tmp;
                }
            }
        }
        return 0;
    }
 
    int dinic()
    {
        int res =0, dd;
        while(bfs())
        {
            for(int i = 0; i <= n; i ++)
                cur[i] = head[i];
            while(dd = dfs(1,INF))
            {
                res += dd;
            }
        }
        return res;
    }
} DC;
 
int main()
{
    scanf("%d %d",&n,&m);
    DJ.init();
    for(int i = 1; i <= m; i++)
    {
        int a, b;
        int c,d;
        scanf("%d %d %d %d",&a,&b,&c,&d);
        DJ.ade(a, b, c, d);
        DJ.ade(b, a, c, d);
    }
    DJ.dj(1);
    DC.init();
    for(int u = 1; u <= n; u ++)
    {
        for(int i = DJ.head[u]; ~i; i = DJ.nxt[i])
        {
            int v = DJ.to[i];
            int cst = DJ.val[i];
            if(d[v] == cst+d[u])
            {
                DC.ade(u, DJ.to[i], DJ.va[i]), DC.ade(DJ.to[i],u,0);
            }
        }
    }
    printf("%d %d\n",d[n],DC.dinic());
 
    return 0;
}

 

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