[NOIP 模擬]疫情延遲 二分+Spfa

題目

描述
由於 A 學校生物實驗室裏那個不負責的數據分析員, 實驗室的病毒威力被錯誤估算,導致了可怕的病毒泄漏,現在病毒即將在校園內傳播開來。
校園裏一共有 n 個建築物, 生物實驗室總是位於一號建築物且在 0 時刻受到病毒入侵。這 n 個建築物由 m 條單向道路相連(也有可能有建築物被孤立) 。每條道路有兩個信息:它的長度,它是多少年前修建的。當一個建築物被病毒入侵,從被入侵的時刻起, 病毒會從所有由這個建築物通向其他建築物的道路按着這條道路的方向以 1 個單位每秒的速度行進。
校長得知這個事情後, 決定放棄這個學校逃跑。 校長總是位於編號爲 n 的行政樓,從零時刻開始需要共 T 秒來逃出行政樓,且逃出行政樓即視爲逃出了這個學校。也就是說,如果病毒入侵行政樓的時間不小於 T,則校長能夠成功逃離。
有些時候,校長沒有足夠的時間逃離,因爲病毒到達行政樓的時間太快了。
爲了讓校長能夠逃離學校, 不得不拆除校園內的一些道路以延緩行政樓的被入侵時間(拆除道路視爲在 0 時刻被拆的道路全部消失) 。當然,如果使得病毒根本無法到達行政樓,也是可以的。
但是, 拆除道路會影響學校的歷史氣息,且破壞程度定義爲拆除的道路中最古老的一條的年齡。請求出保證校長能夠安全撤離的情況下,最小的破壞程度。
輸入
第一行包含三個整數:n, m, T。
接下來 m 行,每行描述一條有向道路。每行 4 個整數,si, ti, Li, Yi,分別表
示這條道路的起點,終點,長度,這條道路的年齡。
輸出
如果不需要拆除任何道路,輸出一行兩個數:-1 和行政樓的被感染時刻(當然
這個時刻大於等於 T) ,以空格隔開。
否則輸出一行包含一個數:最小的破壞程度。
樣例一
delay.in
5 5 15
1 2 6 35
2 4 8 40
1 3 6 45
3 4 3 25
4 5 5 50
delay.out
25
【樣例一說明】

每條邊上的黑字對應這條路的長度,紅字對應年齡。校長將在第 15 秒逃出學校,如果不拆除任何道路,行政樓將在第 14 秒受到入侵。你可以拆除 4 到 5 的道路,使得行政樓免於入侵,這樣的破壞程度是 50。但是最好的方法是拆掉 3 到 4 之間的道路,這樣使得行政樓在第 19 秒受到入侵,校長就可以逃離了。
樣例一
delay.in
3 2 10
1 2 5 30
2 3 6 50
delay.out
-1 11

【數據範圍】
對於 20%的數據,n, m<=10
對於 60%的數據,n, m<=100.
對於 100%的數據,n<=20000, m<=100000.
數據保證在不拆除任何道路的情況下,從 1 號樓到 n 號樓一定存在路徑。

代碼

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

struct Holder{
    int to,next,l,a;
}e[100005];
int head[100005],n,m,t,dis[100005],vis[100005];

struct Data{
    int a,b,c,d;
}data[100005];

int cmp(Data a,Data b){
    return a.d<b.d;
}

int cnt=1;
int Add(int u,int v,int l,int a){
    e[cnt].to=v;
    e[cnt].l=l;
    e[cnt].a=a;
    e[cnt].next=head[u];
    head[u]=cnt++;
}


int Spfa(){
    queue<int> Q;
    Q.push(1);vis[1]=1;dis[1]=0;
    while(!Q.empty()){
        int now=Q.front();Q.pop();vis[now]=1;
        for(int i=head[now];i;i=e[i].next){
            int v=e[i].to;
            if(e[i].l+dis[now]<dis[v]){
                dis[v]=e[i].l+dis[now];
                if(!vis[v]){
                    Q.push(e[i].to);
                }
            }
        }
    }
}

void Initialize(){
    memset(vis,0,sizeof(vis));
    memset(dis,127,sizeof(dis));
    memset(head,0,sizeof(head));
    memset(e,0,sizeof(e));
}

void Read(){
    scanf("%d%d%d",&n,&m,&t);
    int a,b,c,d;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&data[i].a,&data[i].b,&data[i].c,&data[i].d);
        Add(data[i].a,data[i].b,data[i].c,data[i].d);
    }
}

int Judge(int x){
    cnt=1;
    Initialize();
    for(int i=x+1;i<=m;i++){
        Add(data[i].a,data[i].b,data[i].c,data[i].d);
    }
    Spfa();
    if(dis[n]>=t){
        return 1;
    }else{
        return 0;
    }
}
void Bisection(){
    int l=1,r=m,ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(Judge(mid)){
            ans=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    cout<<data[ans].d<<endl;
}
void Solve(){
    if(dis[n]>=t){
        printf("-1 %d\n",dis[n]);
    }else{
        sort(data+1,data+1+m,cmp);
        Bisection();
    }
}
int main(){ 
    Initialize();
    Read();
    Spfa();
    Solve();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章