日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

硬幣問題 tarjan縮點(diǎn)+DP 莫濤

系統(tǒng) 2447 0

2013-09-15 20:04

題目描述

有這樣一個(gè)游戲,桌面上擺了N枚硬幣,分別標(biāo)號(hào)1-N,每枚硬幣有一個(gè)分?jǐn)?shù)C[i]與一個(gè)后繼硬幣T[i]。作為游戲參與者的你,可以購買一個(gè)名為mlj的小機(jī)器人,從任一個(gè)硬幣處開始游戲,然后跳往該硬幣的后繼硬幣T[i],直到你要它停下來,經(jīng)過每個(gè)硬幣時(shí),你可以選擇是否撿起它。當(dāng)某個(gè)mlj機(jī)器人停下來后將被扔掉,這時(shí)你可以選擇結(jié)束游戲或再買一個(gè)mlj機(jī)器人繼續(xù)游戲。

注意,每個(gè)硬幣只能撿一次,而且你不能要求mlj跳向一個(gè)已被撿起的硬幣或從一個(gè)已被撿起的硬幣處開始游戲,因?yàn)槟菢訒?huì)把mlj摔壞的。

?

Your?Task

一開始你的得分是0,每購買一個(gè)mlj機(jī)器人將扣掉你M分,撿起一個(gè)硬幣將得到對應(yīng)的分?jǐn)?shù)C[i],請問如何使得分盡量高(游戲過程中分?jǐn)?shù)可以為負(fù))。

?

輸入文件

第一行兩個(gè)正整數(shù)?N?M

接下來N行,每行兩個(gè)正整數(shù)C[i]?T[i]。

輸出文件

?????一個(gè)整數(shù),最大得分。

?

樣例輸入

? 4?2

?1?3

?2?3

?1?4

?1?3

樣例輸出

? 2

?

數(shù)據(jù)約定

30%???N<=10

60%???N<=300

100???N<=100000??1<=T[i]<=N

運(yùn)算過程及結(jié)果均在Longint范圍內(nèi)

?

因?yàn)橛蠳個(gè)點(diǎn),N條邊,且每個(gè)點(diǎn)都只有一個(gè)后繼,所以可推知圖中一定存在環(huán),所以先用tarjan縮點(diǎn),得到一顆上寬下窄的樹(因?yàn)橐粋€(gè)點(diǎn)只能有一個(gè)后繼,而每個(gè)點(diǎn)可以成為好多點(diǎn)的后繼),為了DP方便,縮點(diǎn)重新建圖時(shí),將邊反向,這時(shí)得到了一顆多叉樹,考慮到可能出現(xiàn)森林,所以用一個(gè)總根節(jié)點(diǎn)將每顆多叉樹的根節(jié)點(diǎn)連接起來。

然后我們得到了一顆多叉樹,問題轉(zhuǎn)化成了樹形DP,由題意可知,因?yàn)榈揭粋€(gè)硬幣可以不撿,所以機(jī)器人的路徑可以重合,那么設(shè)W(X)代表從X節(jié)點(diǎn)向下走可以取得的最大值,假設(shè)X有多個(gè)兒子,因?yàn)楫?dāng)前有一個(gè)機(jī)器人由上方走來到X節(jié)點(diǎn),所以X節(jié)點(diǎn)的兒子中最大的不用X重新買機(jī)器人,剩下的兒子中,如果W(P)>M,就相當(dāng)于在P兒子處再買一個(gè)機(jī)器人,那么更新W(X)值,W(X):=W(P)-M;

      
        {
      
      
        $m 500000000
      
      
        }
      
      

//
      
        By BLADEVIL


      
      
        var
      
      
        

    n, m                        :longint;

    father                      :
      
      
        array
      
      [
      
        0
      
      ..
      
        200010
      
      ] 
      
        of
      
      
         longint;

    start                       :longint;

    flag, fseq                  :
      
      
        array
      
      [
      
        0
      
      ..
      
        100010
      
      ] 
      
        of
      
      
         boolean;

    stack                       :
      
      
        array
      
      [
      
        0
      
      ..
      
        100010
      
      ] 
      
        of
      
      
         longint;

    tot                         :longint;

    time                        :longint;

    low, dfn                    :
      
      
        array
      
      [
      
        0
      
      ..
      
        100010
      
      ] 
      
        of
      
      
         longint;

    key                         :
      
      
        array
      
      [
      
        0
      
      ..
      
        100010
      
      ] 
      
        of
      
      
         longint;

    color                       :longint;

    pre, last, other            :
      
      
        array
      
      [
      
        0
      
      ..
      
        200010
      
      ] 
      
        of
      
      
         longint;

    l                           :longint;

    mark                        :
      
      
        array
      
      [
      
        0
      
      ..
      
        200010
      
      ] 
      
        of
      
      
         longint;

    ans                         :longint;


      
      
        function
      
      
         min(a,b:longint):longint;


      
      
        begin
      
      
        if
      
       a>b 
      
        then
      
       min:=b 
      
        else
      
       min:=
      
        a;


      
      
        end
      
      
        ;




      
      
        procedure
      
      
         connect(x,y:longint);


      
      
        begin
      
      
        

    inc(l);

    pre[l]:
      
      =
      
        last[x];

    last[x]:
      
      =
      
        l;

    other[l]:
      
      =
      
        y;


      
      
        end
      
      
        ;




      
      
        procedure
      
      
         dfs(x:longint);


      
      
        var
      
      
        

    cur                         :longint;


      
      
        begin
      
      
        

    inc(tot);

    stack[tot]:
      
      =
      
        x;

    flag[x]:
      
      =
      
        true;

    fseq[x]:
      
      =
      
        true;

    inc(time);

    dfn[x]:
      
      =
      
        time;

    low[x]:
      
      =
      
        time;

    cur:
      
      =
      
        other[last[x]];

    
      
      
        if
      
      
        not
      
       flag[cur] 
      
        then
      
      
        begin
      
      
        

            dfs(cur);

            low[x]:
      
      =
      
        min(low[x],low[cur]);

        
      
      
        end
      
      
        else
      
      
        if
      
       fseq[cur] 
      
        then
      
       low[x]:=
      
        min(low[x],dfn[cur]);



    cur:
      
      =-
      
        1
      
      
        ;

    
      
      
        if
      
       dfn[x]=low[x] 
      
        then
      
      
        begin
      
      
        

        inc(color);

        
      
      
        while
      
       cur<>x 
      
        do
      
      
        begin
      
      
        

            cur:
      
      =
      
        stack[tot];

            dec(tot);

            fseq[cur]:
      
      =
      
        false;

            key[cur]:
      
      =
      
        color;

            mark[color]:
      
      =mark[color]+
      
        mark[cur];

        
      
      
        end
      
      
        ;

    
      
      
        end
      
      
        ;


      
      
        end
      
      
        ;




      
      
        procedure
      
      
         init;


      
      
        var
      
      
        

    i                           :longint;

    x                           :longint;

    p                           :longint;


      
      
        begin
      
      
        

    read(n,m);  tot:
      
      =
      
        0
      
      ;  color:=
      
        n;

    
      
      
        for
      
       i:=
      
        1
      
      
        to
      
       n 
      
        do
      
       father[i]:=
      
        i;

    
      
      
        for
      
       i:=
      
        1
      
      
        to
      
       n 
      
        do
      
      
        begin
      
      
        

        read(mark[i],x);

        connect(i,x);

        father[x]:
      
      =
      
        i;

    
      
      
        end
      
      
        ;

    
      
      
        for
      
       i:=
      
        1
      
      
        to
      
       n 
      
        do
      
      
        if
      
       father[i]=i 
      
        then
      
       start:=
      
        i;

    
      
      
        if
      
       start=
      
        0
      
      
        then
      
      
         inc(start);

    dfs(start);

    
      
      
        for
      
       i:=
      
        1
      
      
        to
      
       n 
      
        do
      
      
        if
      
       key[i]=
      
        0
      
      
        then
      
      
         dfs(i);



    
      
      
        for
      
       i:=
      
        1
      
      
        to
      
       n 
      
        do
      
      
        begin
      
      
        

        p:
      
      =
      
        other[last[i]];

        
      
      
        if
      
       key[i]<>key[p] 
      
        then
      
      
        begin
      
      
        

            connect(key[p],key[i]);

            father[key[i]]:
      
      =
      
        key[p];

        
      
      
        end
      
      
        ;

    
      
      
        end
      
      
        ;

    
      
      
        for
      
       i:=n+
      
        1
      
      
        to
      
       color 
      
        do
      
      
        if
      
       father[i]=
      
        0
      
      
        then
      
       connect(color+
      
        1
      
      
        ,i);




      
      
        end
      
      
        ;




      
      
        function
      
      
         w(x:longint):longint;


      
      
        var
      
      
        

    p, q                        :longint;

    i, j, maxx                  :longint;

    sum                         :longint;


      
      
        begin
      
      
        

    q:
      
      =
      
        last[x];

    j:
      
      =
      
        0
      
      
        ;

    w:
      
      =
      
        0
      
      
        ;

    w:
      
      =w+
      
        mark[x];

    maxx:
      
      =
      
        0
      
      
        ;

    
      
      
        while
      
       q<>
      
        0
      
      
        do
      
      
        begin
      
      
        

        p:
      
      =
      
        other[q];

        sum:
      
      =
      
        w(p);

        
      
      
        if
      
       sum>m 
      
        then
      
       w:=w+sum-
      
        m;

        
      
      
        if
      
       sum>maxx 
      
        then
      
       maxx:=
      
        sum;

        q:
      
      =
      
        pre[q];

    
      
      
        end
      
      
        ;

    
      
      
        if
      
       maxx<m 
      
        then
      
       w:=w+maxx 
      
        else
      
       w:=w+
      
        m;


      
      
        end
      
      
        ;






      
      
        begin
      
      
        

    assign(input,
      
      
        '
      
      
        coin.in
      
      
        '
      
      
        ); reset(input);

    assign(output,
      
      
        '
      
      
        coin.out
      
      
        '
      
      
        ); rewrite(output);

    init;

    ans:
      
      =w(color+
      
        1
      
      )-
      
        m;

    
      
      
        if
      
       ans>
      
        0
      
      
        then
      
       writeln(ans) 
      
        else
      
       writeln(
      
        0
      
      
        );

    close(input); close(output);




      
      
        end
      
      .
    

?

硬幣問題 tarjan縮點(diǎn)+DP 莫濤


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 滕州市| 长宁县| 尖扎县| 苏尼特左旗| 潞西市| 光泽县| 蒲江县| 子长县| 香港| 调兵山市| 晋江市| 涪陵区| 汉寿县| 株洲市| 嵊泗县| 三门峡市| 布拖县| 衡南县| 军事| 泸溪县| 深水埗区| 遂溪县| 泽普县| 无棣县| 额济纳旗| 汶川县| 平乡县| 宁津县| 大港区| 荣成市| 临潭县| 鄂伦春自治旗| 嫩江县| 米易县| 延津县| 鄱阳县| 山阴县| 鄂伦春自治旗| 磐石市| 志丹县| 广东省|