1. 程式人生 > >bzoj1001 [BeiJing2006]狼抓兔子(網路流dinic演算法||最短路spfa)

bzoj1001 [BeiJing2006]狼抓兔子(網路流dinic演算法||最短路spfa)

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 24017  Solved: 6068
[Submit][Status][Discuss]

Description

現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形:

 

左上角點為(1,1),右下角點為(N,M)(上圖中N=4,M=5).有以下三種類型的道路  1:(x,y)<==>(x+1,y) 
2:(x,y)<==>(x,y+1)  3:(x,y)<==>(x+1,y+1)  道路上的權值表示這條路上最多能夠通過的兔子數,道路是無向的. 左上角和右下角為兔子的兩個窩, 開始時所有的兔子都聚集在左上角(1,1)的窩裡,現在它們要跑到右下解(N,M)的窩中去,狼王開始伏擊 這些兔子.當然為了保險起見,如果一條道路上最多通過的兔子數為K,狼王需要安排同樣數量的K只狼, 才能完全封鎖這條道路,你需要幫助狼王安排一個伏擊方案,使得在將兔子一網打盡的前提下,參與的 狼的數量要最小。因為狼還要去找喜羊羊麻煩.

Input

第一行為N,M.表示網格的大小,N,M均小於等於1000.
接下來分三部分 第一部分共N行,每行M-1個數,表示橫向道路的權值.  第二部分共N-1行,每行M個數,表示縱向道路的權值.  第三部分共N-1行,每行M-1個數,表示斜向道路的權值.  輸入檔案保證不超過10M

Output

輸出一個整數,表示參與伏擊的狼的最小數量.

Sample Input

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

Sample Output

14

HINT

 2015.4.16新加資料一組,可能會卡掉從前可以過的程式。

【解析】:

解法1:網路流dinic演算法,但需要很多地方優化才能不超時,比如

1.dfs過程中,如果某一步,從某點遞迴返回的最大流沒有正數值,則增廣路已經找完,直接把標號d[s]=-1,就能終止遞迴。

2.bfs標號過程中,只要遇到匯點,就立即return,不做後面的無用功

解法2:把每個環路圍成的區域看做一個點,建好圖,從右上角往左下角跑一邊最短路,就能把圖切開。

【程式碼1】:(dinic)

  1. #include <stdio.h>
  2. #include <math.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #include <iostream>  
  6. #include <algorithm> 
  7. #include <queue> 
  8. #define mset(a,i) memset(a,i,sizeof(a))
  9. #define S1(n)    scanf("%d",&n)
  10. #define S2(n,m)  scanf("%d%d",&n,&m)
  11. #define P(n)     printf("%d\n",n)
  12. usingnamespace std;  
  13. typedeflonglong ll;  
  14. constint INF=0x3f3f3f3f;  
  15. constint MAX=1e6+5;  
  16. int n,m;  
  17. struct node{  
  18.     int u,v,w,next;  
  19. }edge[6*MAX];  
  20. int head[MAX];  
  21. int d[MAX];//給點標號 
  22. void add(int u,int v,int w)            //鏈式前向星建圖 
  23. {  
  24.     staticint cnt=0;  
  25.     edge[cnt].v=v;  
  26.     edge[cnt].w=w;  
  27.     edge[cnt].next=head[u];  
  28.     head[u]=cnt++;  
  29. }  
  30. int bfs(int s,int t)  
  31. {  
  32.     mset(d,0);  
  33.     d[s]=1;  
  34.     queue <int> q;  
  35.     q.push(s);  
  36.     while(!q.empty())  
  37.     {  
  38.         int u=q.front();  
  39.         q.pop();  
  40.         if(u==t) return 1;                  //到達匯點 
  41.         for(int i=head[u];i!=-1;i=edge[i].next) //搜增廣路 
  42.         {  
  43.             int v=edge[i].v;               //下一可連通點 
  44.             int w=edge[i].w;               //當前流量 
  45.             if(w&&d[v]==0)             //temp1沒走到 
  46.             {  
  47.                 d[v]=d[u]+1;            //點加1 
  48.                 if(v==t)                 //找到增廣路 
  49.                     return 1;  
  50.                 q.push(v);                 //入佇列 
  51.             }  
  52.         }  
  53.     }  
  54.     return 0;  
  55. }  
  56. int dfs(int s,int t,int maxflow=INF)  
  57. {  
  58.     if(s==t)  
  59.         return maxflow;  
  60.     int i,j,ret=0;  
  61.     for(i=head[s];i!=-1;i=edge[i].next)  
  62.     {  
  63.         int v=edge[i].v;            //下一個可連通點 
  64.         int w=edge[i].w;            //當前點的流量 
  65.         if(w&&d[v]==d[s]+1)  
  66.         {  
  67.             int temp=dfs(v,t,min(maxflow-ret,w)); //下一點,取最大流跟當前流量小的一個 
  68.             edge[i].w-=temp;                  //正向相減 
  69.             edge[i^1].w+=temp;                //反向弧相加 
  70.             ret+=temp;                        //最大流 
  71.             if(ret==maxflow)                  //下一點最大流等於這一點 
  72.             return ret;  
  73.         }  
  74.     }  
  75.     if(!ret)  
  76.         d[s]=-1;  
  77.     return ret;  
  78. }  
  79. int dinic(int s,int t)  
  80. {  
  81.     int ans=0;  
  82.     while(bfs(s,t))  
  83.     {  
  84.         ans+=dfs(s,t);      //dfs返回每次的數量 
  85.     }  
  86.     return ans;  
  87. }  
  88. int main()  
  89. {  
  90.     S2(n,m);  
  91.     mset(head,-1);  
  92. 相關推薦

    bzoj1001 [BeiJing2006]兔子網路dinic演算法||短路spfa

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 24017  Solved: 6

    BZOJ1001 [BeiJing2006]兔子網路小割

    題目可以轉化為:從原圖中選出一個邊集,使得去掉它之後,(1,1)與(n,m)不通  即:以(1,1)為源,(n,m)為匯,求該圖最小割  不過由於節點過多,直接對輸入的圖求最小割的話會超時  轉化:求

    [BZOJ1001][BeiJing2006]兔子 && 平面網路

    傳說這個題可以轉最短路 於是我去轉最短路 於是搞的我無比糾結 連邊麻煩的要死 #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

    bzoj1001: [BeiJing2006]兔子

    題目傳送門 解法: 每一隻兔子就需要一隻狼。 那麼我們只需要求出最多能通過多少隻兔子即可。 然後就派多少隻狼就行了唄。。 因為兔子從哪裡過來的我就在哪裡放狼。 所以狼的數量一定等於最多兔子通過的數量 題目並不要求求方案,所以不需知道兔子從哪過來。

    BZOJ1001 [BeiJing2006]兔子 平面圖轉對偶圖,小割轉短路

    bits ges code inf 如果 對偶圖 += ron oid 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 28885 Solved: 7540[Submit

    BZOJ1001[BeiJing2006]兔子小割網路

    Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=

    bzoj1001 [BeiJing2006]兔子

    script 輸入 wid 最小數 memset dinic nbsp 所有 des 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 12749 Solved: 3

    BZOJ1001: [BeiJing2006]兔子

    div tar name family 設有 amp 兔子 ast mil 【傳送門:BZOJ1001】 簡要題意: 有一個n*m大小的矩陣,假設有一個點(x,y),那麽這個點與(x+1,y)、(x,y+1)、(x+1,y+1)三條邊都連有一條有流量單向邊,且

    BZOJ1001: [BeiJing2006]兔子 (小割轉短路)

    pty closed bsp ini 分割 pan void define 最短 淺析最大最小定理在信息學競賽中的應用---周東 ↑方法介紹 對於一個聯通的平面圖G(滿足歐拉公式) 在s和t間新連一條邊e; 然後建立一個原圖的對偶圖G*,G*中每一個點對應原圖中每一個面,每

    BZOJ1001兔子平面圖轉對偶圖,短路小割

    題面 BZOJ 洛谷 題解 這題用最小割可以直接做 今天再學習了一下平面圖轉對偶圖的做法 大致的思路如下: 1.將源點到匯點中再補一條不與任何線段有交點的邊。這條邊把外側無限大的區域劃

    小割——BZOJ1001 [BeiJing2006]兔子

    http://www.lydsy.com/JudgeOnline/problem.php?id=1001 啊我還能說什麼。。。 dinic網路流直接過了 只要對於每個節點重新編號即可,大眾速度吧。

    BZOJ1001 [Beijing2006] 兔子

    相關資料: 根據最大流-最小割定理,一個網路中,兩個邊緣點之間的最大流等於最小割(最小割就是用一條割線將兩個點分割在兩個圖中,令刪去的邊的總權值最小。因此我們可以建圖,將每個圖(在本題中是每個三角形)作為一個點,點與點之間的連線就等於它們穿過的那條線的權值。在起點和終點間

    網路24題之一】飛行員配對問題+求方案網路dinic演算法求二分圖大匹配

    題面 題目背景 第二次世界大戰時期.. 題目描述 英國皇家空軍從淪陷國徵募了大量外籍飛行員。由皇家空軍派出的每一架飛機都需要配備在航行技能和語言上能互相配合的2 名飛行員,其中1 名是英國飛行員,另1名是外籍飛行員。在眾多的飛行員中,每一名外籍飛行員都可

    1001: [BeiJing2006]兔子[dinic網路]

    現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=4,M=5).有以下三種類型的道路 1:(x,y)<

    BZOJ1001:兔子小割+vector模板

    cout 地形 ++ 能夠 can 圖片 jpg http img 1001: [BeiJing2006]狼抓兔子 Description 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在

    BZOJ1001】【Beijing2006兔子平面圖轉對偶圖:小割+短路

    題目描述 傳送門 題解 題目描述很明顯這就是一道最小割,不過跑最大流的話會TLE。 我們發現這是一個平面圖(什麼是平面圖?),那麼我們就可以參考平面圖轉對偶圖的思想,將這道題轉化成最短路。

    1001: [BeiJing2006]兔子 ()

    地形 opened har 分享 false led www getch data Description 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個

    BZOJ 1001 兔子網絡

    end init false bzoj algo syn i++ vector std 題解:這個建圖很簡單,只要把(1,1)這個點作為超級源,(n,m)作為超級源就可以xjbp。空間要算好。dinic當前弧優化一下就可以跑1500ms #include <io

    [BJOI2006]兔子網絡

    地形 道路 urn pri cout 第三部分 第二部分 void struct 題目描述 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的

    BZOJ1001】【BJOI2006】兔子對偶圖,短路

    Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: