1. 程式人生 > >Dijkstra【P2446】 [SDOI2010]大陸爭霸

Dijkstra【P2446】 [SDOI2010]大陸爭霸

Background

在一個遙遠的世界裡有兩個國家:位於大陸西端的傑森國和位於大陸東端的克里斯國。兩個國家的人民分別信仰兩個對立的神:傑森國信仰象徵黑暗和毀滅的神曾·布拉澤,而克里斯國信仰象徵光明和永恆的神斯普林·布拉澤。

幻想歷8012年1月,傑森國正式宣佈曾·布拉澤是他們唯一信仰的神,同時開始迫害在傑森國的信仰斯普林·布拉澤的克里斯國教徒。

幻想歷8012年3月2日,位於傑森國東部小鎮神諭鎮的克里斯國教徒發動起義。

幻想歷8012年3月7日,神諭鎮的起義被傑森國大軍以殘酷手段鎮壓。

幻想歷8012年3月8日,克里斯國對傑森國宣戰。由數十萬大軍組成的克里斯軍團開至兩國邊境,與傑森軍團對峙。

幻想歷8012年4月,克里斯軍團攻破傑森軍團防線進入神諭鎮,該鎮倖存的克里斯國教徒得到解放。

戰爭隨後進入膠著狀態,曠日持久。戰況慘烈,一時間槍林彈雨,硝煙瀰漫,民不聊生。

Description

幻想歷8012年5月12日深夜,斯普林·布拉澤降下神諭:“Trust me, earn eternal life.”克里斯軍團士氣大增。作為克里斯軍團的主帥,你決定利用這一機會發動奇襲,一舉擊敗傑森國。具體地說,傑森國有N個城市,由M條單向道路連線。神諭鎮是城市1而傑森國的首都是城市N。你只需摧毀位於傑森國首都的曾·布拉澤大神殿,傑森國的信仰,軍隊還有一切就都會土崩瓦解,灰飛煙滅。

為了儘量減小己方的消耗,你決定使用自爆機器人完成這一任務。唯一的困難是,傑森國的一部分城市有結界保護,不破壞掉結界就無法進入城市。而每個城市的結界都是由分佈在其他城市中的一些結界發生器維持的,如果想進入某個城市,你就必須破壞掉維持這個城市結界的所有結界發生器。

現在你有無限多的自爆機器人,一旦進入了某個城市,自爆機器人可以瞬間引爆,破壞一個目標(結界發生器,或是傑森國大神殿),當然機器人本身也會一起被破壞。你需要知道:摧毀傑森國所需的最短時間。

Input

輸入檔案的landcraft.in的第一行兩個正整數N, M。

接下來M行,每行三個正整數ui, vi, wi,表示有一條從城市ui到城市vi的單向道路,自爆機器人通過這條道路需要wi的時間。

之後N行,每行描述一個城市。首先是一個正整數li,維持這個城市結界所使用的結界發生器數目。之後li個1~N之間的城市編號,表示每個結界發生器的位置。如果li = 0,則說明該城市沒有結界保護,保證l1 = 0 。

Output

輸出檔案landcraft.out僅包含一個正整數 ,擊敗傑森國所需的最短時間。

最短路問題,結果因為陣列開小改了好久???

記錄\(dis[x]\)代表到達\(x\)的最短時間。

記錄\(real[x]\)代表到達\(x\)的實際時間。

對於每一個點,我們去更新其相連節點的時候要用\(max(dis[x],real[x])\)去更新。

然後注意建立結界保護的邊的時候建\(li\)\(i\)的有向邊。

因為我搞不清所以直接建雙向邊

然後最後輸出答案輸出\(max(dis[n],real[n])\)即可。

程式碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#define R register

using namespace std;

const int gz=5e4+8;

inline void in(R int &x)
{
    R int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

int head[gz],tot,pr[gz],cnt,hd[gz];

struct cod{int u,v,w;}edge[gz<<1],e[gz<<1];

inline void add(R int x,R int y,R int z)
{
    edge[++tot].u=head[x];
    edge[tot].v=y;
    edge[tot].w=z;
    head[x]=tot;
}

inline void ado(R int x,R int y)
{
    e[++cnt].u=pr[x];
    e[cnt].v=y;
    pr[x]=cnt;
}

int dis[gz],real[gz],n,m;

bool vis[gz];

struct hop
{
    int u,d;
    bool operator <(const hop&a)const
    {
        return d>a.d;
    };
};

inline void dij()
{
    for(R int i=1;i<=n;i++)dis[i]=2147483644;
    priority_queue<hop>q;dis[1]=real[1]=0;
    q.push((hop){1,0});
    while(!q.empty())
    {
        R int u=q.top().u;q.pop();
        if(vis[u])continue;
        vis[u]=true;
        R int now=max(dis[u],real[u]);
        for(R int i=head[u];i;i=edge[i].u)
        {
            if(dis[edge[i].v]>now+edge[i].w)
            {
                dis[edge[i].v]=now+edge[i].w;
                if(hd[edge[i].v]==0)
                    q.push((hop){edge[i].v,max(dis[edge[i].v],real[edge[i].v])});
            }
        }
        for(R int i=pr[u];i;i=e[i].u)
        {
            hd[e[i].v]--;
            real[e[i].v]=max(real[e[i].v],now);
            if(hd[e[i].v]==0)
                q.push((hop){e[i].v,max(real[e[i].v],dis[e[i].v])});
        }
    }
    printf("%d\n",max(real[n],dis[n]));
}

int main()
{
    in(n),in(m);
    for(R int i=1,x,y,z;i<=m;i++)
    {
        in(x),in(y),in(z);
        if(x==y)continue;
        add(x,y,z);
    }
    for(R int i=1,x;i<=n;i++)
    {
        in(x);hd[i]=x;
        for(R int fk;x;x--)
            in(fk),ado(fk,i),ado(i,fk);
    }
    dij();
}