• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Better man

            改變性格 改變命運(yùn)!

             

            差分約束系統(tǒng)(zoj1508)

            給出一組限制條件 a[i] - a[j] ≥ k 或 a[i] - a[j] ≤ k。
            要你求出a[t] - a[s]的最小值或最大值。

            先舉一個(gè)題目的例子:poj1201.
            題目大意是,有一個(gè)集合S。已知其滿足以下一些條件:
            對于給出的n組 a[i] b[i] c[i],有從a[i]~b[i]這連續(xù)的k個(gè)整數(shù)中,至少有c[i]個(gè)在集合S內(nèi)。求S最少的元素個(gè)數(shù)。

            這個(gè)題目轉(zhuǎn)化為我們的差分約束系統(tǒng)如下:
            如果i∈S,則t[i]=1,否則t[i]=0。另s[i] = ∑t[j] (j = 0 ~ i),這樣子,題目的條件就可以用下面的式子表示:
            s[b[i]] - s[a[i]-1] ≥ c[i]
            s[i] - s[i+1] ≥ -1
            s[i+1] - s[i] ≥ 0
            注意后面兩個(gè)式子是s先天的性質(zhì)。
            我們要求的就是s[n] - s[-1]的最小值(因?yàn)轭}目都是非負(fù)的嘛)。

            然后我們介紹解決差分約束問題的方法:Bellman-Ford算法,是不是很神奇呢?沒錯(cuò),差分約束系統(tǒng)可以通過轉(zhuǎn)換成圖論最短路問題來解決:
            注意到最短路算法的松弛操作:if (d[j] > d[i] + w[i][j]) d[j] = d[i] + w[i][j]。
            這其中的三角形不等式:d[j] ≤ d[i] + w[i][j]簡單變形就成了d[i] - d[j] >= -w[i][j]。這樣就圖形的最短路就維護(hù)了一個(gè)不等式組。所以,我們可以建立一個(gè)圖:對于每一個(gè)不等式s[i] - s[j] >= c,就從j連一條指向i的邊,其中邊的權(quán)值c,這樣求一個(gè)最長路,就是d[n] - d[-1]就是s[n] - s[-1]的最小值了,且對應(yīng)的方案就是s[i] = d[i]。

            有的同學(xué)要問了:無解怎么辦啊?很簡單,你將會(huì)發(fā)現(xiàn)Bellman-Ford算法如果找出了”負(fù)權(quán)回路”,那么該系統(tǒng)無解。只要系統(tǒng)無解,就必然存在”負(fù)權(quán)圈”。
            那么如果求s[n] - s[-1]的最小值呢?其實(shí)和上面的方法類似了,大家可以自己推導(dǎo)一下。而且有很多問題僅僅要你給出是否有解的判斷,那就不要想那么多了。

            實(shí)際上是求最長路,其實(shí)就是把松弛操作的符號改變即可

            其實(shí)此題可以用spfa實(shí)現(xiàn),效率很高

            開始做此題時(shí)

            連續(xù)超時(shí)很久

            此題每次要進(jìn)行三次松弛操作

             1 for(int j=Min;j<Max;++j)
             2 {
             3       if(d[j]!=INT_MIN&&d[j]>d[j+1])
             4       {
             5             d[j+1]=d[j];
             6             update=0;
             7       }
             8 }
             9 for(int j=Max;j>Min;--j)
            10 {
            11       if(d[j]!=INT_MIN&&d[j]-1>d[j-1])
            12       {
            13             update=0;
            14             d[j-1]=d[j]-1;
            15       }
            16 }
            一開始將兩個(gè)松弛操作合并到一起進(jìn)行

            超時(shí)

            第二次分開

            仍然超時(shí)

            第三次

            改變松弛的順序

            即第三個(gè)松弛從上到下(之前是從下到上)

            這樣做的目的就是避免了重復(fù)的松弛操作!

             1 #include <iostream>
             2 using namespace std;
             3 struct Edge
             4 {
             5       int x,y,d;
             6 }edge[50000+5];
             7 int n;
             8 int d[50000+5];
             9 int main()
            10 {      
            11      while(scanf("%d",&n)!=EOF)
            12      {
            13             int Min=INT_MAX;
            14             int Max=INT_MIN;
            15             for(int i=0;i<n;++i)
            16             {
            17                   scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].d);
            18                   if(--edge[i].x<Min)Min=edge[i].x;
            19                   if(edge[i].y>Max)Max=edge[i].y;
            20             }
            21             int tmp=Max-Min+1;
            22             for(int i=Min;i<=Max;++i)
            23                   d[i]=INT_MIN;
            24             d[Min]=0;
            25             for(int i=0;i<tmp;++i)
            26             {
            27                   bool update=1;
            28                   for(int j=0;j<n;++j)
            29                   {
            30                         if(d[edge[j].x]!=INT_MIN&&d[edge[j].y]<d[edge[j].x]+edge[j].d) 
            31                         {
            32                               update=0;
            33                               d[edge[j].y]=d[edge[j].x]+edge[j].d;
            34                         }
            35                   }
            36                   for(int j=Min;j<Max;++j)
            37                   {
            38                         if(d[j]!=INT_MIN&&d[j]>d[j+1])
            39                         {
            40                               d[j+1]=d[j];
            41                               update=0;
            42                         }
            43                     }
            44                   for(int j=Max;j>Min;--j)
            45                   {
            46                         if(d[j]!=INT_MIN&&d[j]-1>d[j-1])
            47                         {
            48                               update=0;
            49                               d[j-1]=d[j]-1;
            50                         }
            51                   }
            52                   if(update)break;
            53             }
            54             printf("%d\n",d[Max]-d[Min]);
            55       }
            56       return 0;
            57 }

            posted on 2009-02-05 11:32 SHFACM 閱讀(1526) 評論(1)  編輯 收藏 引用

            評論

            # re: 差分約束系統(tǒng)(zoj1508)[未登錄] 2011-02-19 11:16 lj

            終于看懂些了!多謝樓主!  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章分類

            文章檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久青青草原亚洲av无码| 国内高清久久久久久| 久久免费高清视频| 久久99国产精品成人欧美| 精品久久久久久无码不卡| 亚洲精品乱码久久久久久按摩 | 久久久WWW成人免费毛片| 久久久久97国产精华液好用吗| 久久久久久伊人高潮影院| 久久九九亚洲精品| 中文精品久久久久人妻不卡| 一本伊大人香蕉久久网手机| 久久精品国产2020| 久久人人超碰精品CAOPOREN| 久久久久亚洲AV无码专区体验| 久久久久国产一区二区| 精品久久久久久亚洲精品 | 国产午夜福利精品久久| 囯产精品久久久久久久久蜜桃| 精品国产91久久久久久久a| 久久精品人人做人人爽97 | 国产精品视频久久久| 日日狠狠久久偷偷色综合0| 色偷偷888欧美精品久久久| 伊人久久大香线蕉亚洲| 婷婷久久综合九色综合九七| 国产成人精品久久亚洲| 久久99精品国产麻豆宅宅| 久久综合88熟人妻| 久久婷婷五月综合色奶水99啪| 一本色道久久综合亚洲精品| 亚洲欧美国产精品专区久久| 日本精品一区二区久久久| 激情综合色综合久久综合| 久久精品成人欧美大片| 久久99精品国产麻豆不卡| 精品多毛少妇人妻AV免费久久| 青春久久| 亚洲综合精品香蕉久久网| 麻豆成人久久精品二区三区免费| 性做久久久久久久|