标签:iostream 记录 inf style turn for min div 起点
完全体网络流。。
拿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; }
标签:iostream 记录 inf style turn for min div 起点
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9521288.html