Bzoj 1927: [Sdoi2010]星際競速(網絡流)

1927: [Sdoi2010]星際競速
Time Limit: 20 Sec Memory Limit: 259 MB
Description
  10年一度的銀河系賽車大賽又要開始了。作爲全銀河最盛大的活動之一,奪得這個項目的冠軍無疑是很多人的
夢想,來自傑森座α星的悠悠也是其中之一。賽車大賽的賽場由N顆行星和M條雙向星際航路構成,其中每顆行星都
有一個不同的引力值。大賽要求車手們從一顆與這N顆行星之間沒有任何航路的天體出發,訪問這N顆行星每顆恰好
一次,首先完成這一目標的人獲得勝利。由於賽制非常開放,很多人駕駛着千奇百怪的自制賽車來參賽。這次悠悠
駕駛的賽車名爲超能電驢,這是一部凝聚了全銀河最尖端科技結晶的夢幻賽車。作爲最高科技的產物,超能電驢有
兩種移動模式:高速航行模式和能力爆發模式。在高速航行模式下,超能電驢會展開反物質引擎,以數倍於光速的
速度沿星際航路高速航行。在能力爆發模式下,超能電驢脫離時空的束縛,使用超能力進行空間跳躍——在經過一
段時間的定位之後,它能瞬間移動到任意一個行星。天不遂人願,在比賽的前一天,超能電驢在一場離子風暴中不
幸受損,機能出現了一些障礙:在使用高速航行模式的時候,只能由每個星球飛往引力比它大的星球,否則賽車就
會發生爆炸。儘管心愛的賽車出了問題,但是悠悠仍然堅信自己可以取得勝利。他找到了全銀河最聰明的賢者——
你,請你爲他安排一條比賽的方案,使得他能夠用最少的時間完成比賽。
Input
  第一行是兩個正整數N,M。第二行N個數A1~AN,其中Ai表示使用能力爆發模式到達行星i所需的定位時間。接下
來M行,每行3個正整數ui,vi,wi,表示在編號爲ui和vi的行星之間存在一條需要航行wi時間的星際航路。輸入數據
已經按引力值排序,也就是編號小的行星引力值一定小,且不會有兩顆行星引力值相同。
Output
  僅包含一個正整數,表示完成比賽所需的最少時間。
Sample Input
3 3
1 100 100
2 1 10
1 3 1
2 3 1
Sample Output
12
HINT
  說明:先使用能力爆發模式到行星1,花費時間1。然後切換到高速航行模式,航行到行星2,花費時間10。之
後繼續航行到行星3完成比賽,花費時間1。雖然看起來從行星1到行星3再到行星2更優,但我們卻不能那樣做,因
爲那會導致超能電驢爆炸。N≤800,M≤15000。輸入數據中的任何數都不會超過106。輸入數據保證任意兩顆行星
之間至多存在一條航道,且不會存在某顆行星到自己的航道。
Source
第一輪Day2

/*
網絡流.
精妙的建圖.
二元組(c,f). 
將每個點i拆成i和i'
由S向i連邊(1,0)
由S向i'連邊(1,w)
由i'向T連邊(1,0)
由u向v'連邊  (i,w)
相當於能量爆發與高速行駛之間的最優抉擇.
分兩種情況 
1.由源點流來:指在某一時刻瞬移到該星球
2.由入點流來:指由其他星球沿航路到該星球
*/
#include<iostream>
#include<cstdio>
#include<queue>
#define MAXN 15001
using namespace std;
int n,m,S,T,cut=1,ans,head[MAXN],dis[MAXN],bao[MAXN],fa[MAXN];
struct edge{int u,v,c,f,next;}e[MAXN*20];
bool b[MAXN];
queue<int>q;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
void add(int u,int v,int c,int f)
{
    e[++cut].u=u,e[cut].v=v;e[cut].c=c;e[cut].f=f;e[cut].next=head[u];head[u]=cut;
    e[++cut].u=u;e[cut].v=v;e[cut].c=0;e[cut].f=-f;e[cut].next=head[u];head[u]=cut;
}
bool bfs(int t)
{
    for(int i=0;i<=T;i++) dis[i]=1e7;dis[S]=0;
    dis[S]=0;q.push(S);
    while(!q.empty())
    {
        int u=q.front();q.pop();b[u]=false;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].f&&e[i].c)
            {
                dis[v]=dis[u]+e[i].f;fa[v]=i;
                if(b[v]!=t) b[v]=t,q.push(v);
            }
        }
    }
    return dis[T]!=1e7;
}
void mincost()
{
    int t=1;
    while(bfs(t))
    {
        int tmp=fa[T],x=1e7;
        while(tmp) x=min(x,e[tmp].c),tmp=fa[e[tmp].u];
        tmp=fa[T];
        while(tmp)
        {
            e[tmp].c-=x;
            e[tmp^1].c+=x;
            tmp=fa[e[tmp].u];
        }
        ans+=dis[T]*x;
        t++;
    }
}
int main()
{
//  freopen("starrace.in","r",stdin);
//  freopen("starrace.out","w",stdout);
    int x,y,z;
    n=read(),m=read();S=0,T=2*n+1;
    for(int i=1;i<=n;i++)
    {
        x=read();
        add(S,i,1,0),add(S,i+n,1,x);
        add(i,i+n,1,0);
        add(i+n,T,1,0);
    }
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        if(x>y) swap(x,y);
        add(x,y+n,1,z);
    }
    mincost();
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章