1. 程式人生 > >POJ 3281 Dining 【最大流】

POJ 3281 Dining 【最大流】

using esp push_back 鄰接 reverse path 出發 sin name

完全體網絡流。。

拿vector實現了一次,這樣的話網絡流的所有實現方法我都寫過一遍了

#include<iostream>
#include<deque>
#include<vector>
#include<cstring>
#define INF 2e9
using namespace std;

int N,F,D,T;

struct edge{
    int v,cap,reverse;
};
vector<int> edges[1005];//鄰接表 
vector<edge> bian;//所有的邊都存在裏面 

void
addedge(int u,int v,int cap){//u到v一條邊,再加一條反向邊 edge e; e.cap=cap; e.v=v; e.reverse=bian.size()+1;//這條邊的反邊將建在這條邊之後(這條邊建完後在bian.size()的位置) bian.push_back(e); edges[u].push_back(bian.size()-1); e.cap=0; e.v=u; e.reverse=bian.size()-1; bian.push_back(e); edges[v].push_back(bian.size()
-1); } int layer[1005],vis[1005]; bool count_layer(){ memset(layer,0,sizeof(layer)); deque<int> q; layer[0]=1; q.push_back(0); while( !q.empty() ){ int u = q.front(); q.pop_front(); if( u==T ) return true; for(int i=0;i<edges[u].size();i++){//所有以u為起點的邊的邊的索引 edge &e = bian[ edges[u][i] ];
int v=e.v; if( !layer[v] && e.cap>0 ){ layer[v] = layer[u] + 1; q.push_back( v ); } } } return false; } int dinic(){ int max_flow=0; while( count_layer() ){ memset(vis,0,sizeof(vis)); deque<int> q,path;//記錄一路走過來的【點】和【邊的索引】 q.push_back(0); vis[0]=1; while(!q.empty()){ int u = q.back(); if( u==T ){ int min_u,min_v,min_flow=INF; int p=0;//從0點出發 for(int i=0;i<path.size();i++){ edge &e = bian[ path[i] ]; if( e.cap<min_flow ){ min_u=p; min_flow=e.cap; } p=e.v; } p=0; max_flow+=min_flow; for(int i=0;i<path.size();i++){ edge &e = bian[ path[i] ]; e.cap-=min_flow; bian[e.reverse].cap+=min_flow; } //回溯 while( !q.empty() && q.back()!=min_u ){ vis[ q.back() ]=0; q.pop_back(); path.pop_back(); } } else{//T邊 int i; for(i=0;i<edges[u].size();i++){ edge &e = bian[ edges[u][i] ]; if( layer[e.v]==layer[u]+1 && !vis[e.v] && e.cap>0 ){ vis[e.v]=1; q.push_back( e.v ); path.push_back( edges[u][i] ); break; } } if(i==edges[u].size()) { q.pop_back(); path.pop_back(); } } } } return max_flow; } int main(){ //food編號1 - F //把一頭牛拆成兩頭 //cows1編號F+1 - F+N //cows2編號F+N+1 - F+N+N //drink編號F+2N+1 - F+2N+D cin>>N>>F>>D; T=N+N+F+D+1; for(int i=1;i<=N;i++){ int fi,di,food,drink; cin>>fi>>di; for(int j=1;j<=fi;j++) cin>>food,addedge(food,F+i,1);//food到奶牛1建一條邊 for(int j=1;j<=di;j++) cin>>drink,addedge(F+N+i,F+2*N+drink,1);//從奶牛2到drink建一條邊 } for(int i=F+1;i<=F+N;i++) addedge(i,i+N,1);//奶牛1到奶牛2建一條邊 for(int i=1;i<=F;i++) addedge(0,i,1);//從源點0到所有food建邊 for(int i=F+2*N+1;i<=F+2*N+D;i++) addedge(i,T,1); //從所有drink到匯點F+D+2*N+1建邊 cout<<dinic(); return 0; }

POJ 3281 Dining 【最大流】