• <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

            改變性格 改變命運!

             

            差分約束系統(zoj1508)

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

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

            這個題目轉化為我們的差分約束系統如下:
            如果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
            注意后面兩個式子是s先天的性質。
            我們要求的就是s[n] - s[-1]的最小值(因為題目都是非負的嘛)。

            然后我們介紹解決差分約束問題的方法:Bellman-Ford算法,是不是很神奇呢?沒錯,差分約束系統可以通過轉換成圖論最短路問題來解決:
            注意到最短路算法的松弛操作: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]。這樣就圖形的最短路就維護了一個不等式組。所以,我們可以建立一個圖:對于每一個不等式s[i] - s[j] >= c,就從j連一條指向i的邊,其中邊的權值c,這樣求一個最長路,就是d[n] - d[-1]就是s[n] - s[-1]的最小值了,且對應的方案就是s[i] = d[i]。

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

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

            其實此題可以用spfa實現,效率很高

            開始做此題時

            連續超時很久

            此題每次要進行三次松弛操作

             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 }
            一開始將兩個松弛操作合并到一起進行

            超時

            第二次分開

            仍然超時

            第三次

            改變松弛的順序

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

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

             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 閱讀(1512) 評論(1)  編輯 收藏 引用

            評論

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

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

            導航

            統計

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章分類

            文章檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            三级片免费观看久久| 免费一级欧美大片久久网| 久久久久久久波多野结衣高潮| 久久午夜免费视频| 色婷婷综合久久久久中文| 精品久久久久久久久中文字幕| 久久本道久久综合伊人| 无码人妻少妇久久中文字幕蜜桃 | 97久久精品无码一区二区天美| 狠狠色丁香久久综合婷婷| 亚洲v国产v天堂a无码久久| 国内精品久久久久久99蜜桃 | 亚洲av成人无码久久精品 | 久久精品无码一区二区WWW| 狠狠狠色丁香婷婷综合久久五月 | 久久精品国产精品亚洲精品| 欧美日韩精品久久久免费观看 | 久久久久99精品成人片| 97久久超碰国产精品旧版| 国产精品久久久久久久久软件| 国产999精品久久久久久| 国内精品久久久久影院一蜜桃| 亚洲乱码精品久久久久..| 久久久久九九精品影院| 国产Av激情久久无码天堂| 久久久久亚洲av无码专区| 中文字幕久久精品| 亚洲国产精品成人AV无码久久综合影院| 精品综合久久久久久97超人| 日韩精品久久久久久久电影蜜臀| 中文成人无码精品久久久不卡| 久久久久国产精品嫩草影院| 国产激情久久久久影院| 国产精品狼人久久久久影院| 国产精品美女久久久久久2018| 久久青青草原亚洲av无码app| 狠狠色噜噜色狠狠狠综合久久 | 亚洲国产精品一区二区三区久久| 久久久中文字幕日本| 亚洲精品tv久久久久| 国产精品久久久久久久久久影院|