Poj 3281 Regional Chengdu Food(Dicnic)
生活随笔
收集整理的這篇文章主要介紹了
Poj 3281 Regional Chengdu Food(Dicnic)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
網絡流最大流的優化算法Dicnic,每一步對原圖進行分層,然后用DFS求增廣路。時間復雜度是O(n^2*m) 。
Poj 3281 和 9.16號成都regional網絡賽food那道題,都是很好的模板題。。
以food那題為例,這樣建圖:設一個源點,每一種food為一層,每個人分成兩部分,people1 people2兩層,每種飲料是一層,然后是一個匯點。
每一種食物的個數,即為源點到那種food的流量;
飲料同理。
每一個人只消耗一種一個食物和一種一個飲料,因此每種食物(或飲料)與人的連線,流量為1?
people1與people2的間的流量為1
模板放這兒先。
POJ 3281
#include<stdio.h> #include<string.h> const int EDGE_NUM = 20001;//邊數 const int POINT_NUM = 501;//點數 struct edge {int v;//點int next;//下一邊int value;//當前邊流量 } edge[2*EDGE_NUM]; //邊信息,以鄰接表形式存儲int p[POINT_NUM];//p[i]記錄最后一條以i為起點的邊的id,即以i為起點的最后一條邊為edge[p[i]],而edge[p[i]].next則為以i為起點的倒數第二條邊,以此類推 int level[POINT_NUM];//level[i]記錄i點的層次 int que[POINT_NUM],out[POINT_NUM];//輔助數組 int edgeNumber;void init() {edgeNumber = 0;memset(p,-1,sizeof(p)); }inline void addEdge(int from,int to,int value)//添加邊,以鄰接表形式存儲 {edge[edgeNumber].v = to;edge[edgeNumber].value = value;edge[edgeNumber].next = p[from];p[from] = edgeNumber++; }int Dinic(int source,int sink,int n) {int i,maxFlow = 0;while(true){int head,tail;for(i=0; i<n; i++)level[i] = 0;level[source] = 1;//源點為第一層head = 0;tail = 0;que[0] = source;//que這里當隊里使用while(head<=tail)//BFS該剩余圖,計算每個可達點層次{int cur = que[head++];for(i=p[cur]; i!=-1; i=edge[i].next){if(edge[i].value>0&&level[edge[i].v]==0){level[edge[i].v] = level[cur]+1;que[++tail] = edge[i].v;}}}if(level[sink]==0)break;//不存在增廣路for(i=0; i<n; i++)out[i]=p[i]; //out[i]動態記錄可用邊int q = -1;//q為已經搜索到的點的個數,que存放途徑邊信息while(true)//DFS剩余圖,查找增廣路{if(q<0)//當前路為空{int cur = out[source];for(; cur!=-1; cur=edge[cur].next) //查找第一條邊{if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==2)//合法第一條邊必須滿足:1.流量大于0;2.終點有可用邊 3:終點層次為2break;}if(cur==-1)break;//找不到第二層,當前剩余圖已經沒有增廣路que[++q]=cur;//存入第一條邊idout[source]=edge[cur].next;}int curnode = edge[que[q]].v;//當前路的終點if(curnode==sink)//找到一條增廣路{int thisflow = edge[que[0]].value;//thisflow為當前增廣路的流量int index = 0;//標記最小流量邊的idfor(i=1; i<=q; i++){if(thisflow>edge[que[i]].value){thisflow=edge[que[i]].value;index = i;}}maxFlow+=thisflow;for(i=0; i<=q; i++){edge[que[i]].value-=thisflow;edge[que[i]^1].value+=thisflow;//與其方向相反的邊}q = index-1;//查找下一條增廣路時可直接使用當前路的前q條邊}else//尚未找到匯點{int cur = out[curnode];for(; cur!=-1; cur=edge[cur].next){if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==level[curnode]+1)break;}if(cur==-1)//沒有下一條路{out[curnode]=-1;//標記當前點的可達邊為0q--;}else{que[++q]=cur;out[curnode]=edge[cur].next;//下一次搜索時可達邊從edge[cur].next開始查找}}}}return maxFlow; }int main() {int Nn,Ff,Dd;while(scanf("%d%d%d",&Nn,&Ff,&Dd)!=EOF){init();int foodstart = 1;int cow1 = Ff+2;int cow2 = cow1+Nn+1;int drinkstart = cow2+Nn+1;int end = drinkstart+Dd+1;int i;for(i=0; i<Nn; i++) //添加牛邊{addEdge(cow1+i,cow2+i,1);addEdge(cow2+i,cow1+i,0);}for(i=0; i<Ff; i++) //添加食物邊{addEdge(0,foodstart+i,1); addEdge(foodstart+i,0,0);}for(i=0; i<Dd; i++) //添加飲料{addEdge(drinkstart+i,end,1); addEdge(end,drinkstart+i,0);}for(i=0; i<Nn; i++){int f,d;scanf("%d%d",&f,&d);int x;while(f--){scanf("%d",&x);x--;addEdge(foodstart+x,cow1+i,1);addEdge(cow1+i,foodstart+x,0);}while(d--){scanf("%d",&x);x--;addEdge(cow2+i,drinkstart+x,1);addEdge(drinkstart+x,cow2+i,0);}}printf("%d\n",Dinic(0,end,end+1));}return 0; }
成都regional網絡賽
#include<cstdio> #include<cstring> #include <memory.h> const int EDGE_NUM = 100001;//邊數 const int POINT_NUM = 250;//點數 struct edge {int v;//點int next;//下一邊int value;//當前邊流量 } edge[2*EDGE_NUM]; //邊信息,以鄰接表形式存儲int p[POINT_NUM];//p[i]記錄最后一條以i為起點的邊的id,即以i為起點的最后一條邊為edge[p[i]],而edge[p[i]].next則為以i為起點的倒數第二條邊,以此類推 int level[POINT_NUM];//level[i]記錄i點的層次 int que[POINT_NUM],out[POINT_NUM];//輔助數組 int edgeNumber; int food[250]; int drink[250]; void init() {edgeNumber = 0;memset(p,-1,sizeof(p)); } void addEdge(int from,int to,int value)//添加邊,以鄰接表形式存儲 {edge[edgeNumber].v = to;edge[edgeNumber].value = value;edge[edgeNumber].next = p[from];p[from] = edgeNumber++; }int Dinic(int source,int sink,int n) {int i,maxFlow = 0;while(true){int head,tail;for(i=0; i<n; i++)level[i] = 0;level[source] = 1;//源點為第一層head = 0;tail = 0;que[0] = source;//que這里當隊里使用while(head<=tail)//BFS該剩余圖,計算每個可達點層次{int cur = que[head++];for(i=p[cur]; i!=-1; i=edge[i].next){if(edge[i].value>0&&level[edge[i].v]==0){level[edge[i].v] = level[cur]+1;que[++tail] = edge[i].v;}}}if(level[sink]==0)break;//不存在增廣路for(i=0; i<n; i++)out[i]=p[i]; //out[i]動態記錄可用邊int q = -1;//q為已經搜索到的點的個數,que存放途徑邊信息while(true)//DFS剩余圖,查找增廣路{if(q<0)//當前路為空{int cur = out[source];for(; cur!=-1; cur=edge[cur].next) //查找第一條邊{if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==2)//合法第一條邊必須滿足:1.流量大于0;2.終點有可用邊 3:終點層次為2break;}if(cur==-1)break;//找不到第二層,當前剩余圖已經沒有增廣路que[++q]=cur;//存入第一條邊idout[source]=edge[cur].next;}int curnode = edge[que[q]].v;//當前路的終點if(curnode==sink)//找到一條增廣路{int thisflow = edge[que[0]].value;//thisflow為當前增廣路的流量int index = 0;//標記最小流量邊的idfor(i=1; i<=q; i++){if(thisflow>edge[que[i]].value){thisflow=edge[que[i]].value;index = i;}}maxFlow+=thisflow;for(i=0; i<=q; i++){edge[que[i]].value-=thisflow;edge[que[i]^1].value+=thisflow;//與其方向相反的邊}q = index-1;//查找下一條增廣路時可直接使用當前路的前q條邊}else//尚未找到匯點{int cur = out[curnode];for(; cur!=-1; cur=edge[cur].next){if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==level[curnode]+1)break;}if(cur==-1)//沒有下一條路{out[curnode]=-1;//標記當前點的可達邊為0q--;}else{que[++q]=cur;out[curnode]=edge[cur].next;//下一次搜索時可達邊從edge[cur].next開始查找}}}}return maxFlow; }int main() {int Nn,Ff,Dd;while(scanf("%d%d%d",&Nn,&Ff,&Dd)!=EOF){init();int foodstart = 1;int cow1 = Ff+1;int cow2 = cow1+Nn+1;int drinkstart = cow2+Nn+1;int end = drinkstart+Dd+1;for(int i=1;i<=Ff;i++)scanf("%d",&food[i]);for(int i=1;i<=Dd;i++)scanf("%d",&drink[i]);int i;for(i=0; i<Nn; i++) //添加牛邊{addEdge(cow1+i,cow2+i,1);addEdge(cow2+i,cow1+i,0);}for(i=0; i<Ff; i++) //添加食物邊{addEdge(0,foodstart+i,food[i+1]); //每一種食物路徑的流量。addEdge(foodstart+i,0,0);}for(i=0; i<Dd; i++) //添加飲料{addEdge(drinkstart+i,end,drink[i+1]);addEdge(end,drinkstart+i,0);}char t;for(i=0; i<Nn; i++){getchar();for(int j=0; j<Ff; j++){scanf("%c",&t);if(t=='Y'){addEdge(foodstart+j,cow1+i,1);addEdge(cow1+i,foodstart+j,0);}}}for(i=0; i<Nn; i++){getchar();for(int j=0; j<Dd; j++){scanf("%c",&t);if(t=='Y'){addEdge(cow2+i,drinkstart+j,1);addEdge(drinkstart+j,cow2+i,0);}}}printf("%d\n",Dinic(0,end,end+1));}return 0; }
轉載于:https://www.cnblogs.com/MicZ/archive/2012/09/17/2785369.html
總結
以上是生活随笔為你收集整理的Poj 3281 Regional Chengdu Food(Dicnic)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: T_SQL的 FOR XML PATH
- 下一篇: IBM 2013策略发布:大数据和分析、