标签:距离 分享 false amp i++ 反向 span stream 建图
很好理解的,,按最大流思路理解就行 用优先队列优化复杂度低一点
//#include<iostream> //#include<cstdio> //#include<cstring> //#include<cmath> //#include<queue> //#include<set> //#include<algorithm> //#include<map> //#define maxn 200005 //typedef long long ll; //#define inf 100000009 //using namespace std; //struct edge{ //int to,cap,cost,rev; //终点,容量,费用,反向边 //}; //int n,V; //vector<edge>G[maxn]; //int dis[maxn]; //int prevv[maxn]; //最短路中的前驱结点 //int preve[maxn]; //最短路中对应的边 // ////向图中增加一条从from到头容量为cap费用为cost的边; //void add_edge(int from,int to,int cap,int cost) //{ // G[from].push_back((edge){to,cap,cost,G[to].size()}); // G[to].push_back((edge){from,0,-cost,G[from].size()-1}); //} // ////求解从s到t流量为f的最小费用流 ////如果不能再增广则返回-1 //int min_cost_flow(int V,int s,int t,int f) //{ // int res=0; // //cout<<V<<endl; // while(f>0) // { // fill(dis,dis+V,inf); // dis[s]=0; // bool vis=true; // while(vis) // { // //cout<<dis[3]<<endl; // // cout<<"a"<<endl; // vis=false; // //cout<<"a"<<endl; // // cout<<n<<endl; // for(int i=0;i<V;i++) // { // //cout<<dis[i]<<endl; // if(dis[i]==inf)continue; // for(int j=0;j<G[i].size();j++) // { // edge &e=G[i][j]; // //cout<<e.cap<<endl; // if(e.cap>0&&dis[e.to]>dis[i]+e.cost) // { // dis[e.to]=dis[i]+e.cost; // prevv[e.to]=i; // preve[e.to]=j; // vis=true; // //cout<<"vis"<<endl; // } // } // } // // cout<<vis<<endl; // } // if(dis[t]==inf)return -1; //表示不能增广 // //沿s到t的最短路尽量增广 // int d=f; // for(int i=t;i!=s;i=prevv[i]) // { // d=min(d,G[prevv[i]][preve[i]].cap); // } // f-=d; // res+=d*dis[t]; // for(int i=t;i!=s;i=prevv[i]) // { // edge &e=G[prevv[i]][preve[i]]; // e.cap-=d; // G[i][e.rev].cap+=d; // } // } // return res; //} //int main() //{ // int n,k; // cin>>n>>k; // int s1,t1,f1; // int x,y,z,l; // for(int i=0;i<k;i++) // { // cin>>x>>y>>z>>l; // add_edge(x,y,z,l); // } // cin>>s1>>t1>>f1; // cout<<min_cost_flow(n,s1,t1,f1)<<endl; // return 0; //} #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 20005 #define inf 1000000009 typedef long long ll; using namespace std; typedef pair<int,int>P; //first保存最短距离 second保存顶点编号 struct edge{ int to,cap,cost,rev; }; vector<edge>G[maxn]; int h[maxn]; //顶点的势 int dis[maxn]; //最短距离 int prevv[maxn]; //最短路中的前驱结点 int preve[maxn]; //最短路中的边 //建图 void add_edge(int from,int to,int cap,int cost) { G[from].push_back((edge){to,cap,cost,G[to].size()}); G[to].push_back((edge){from,0,-cost,G[from].size()-1}); } //求解从s到t流量为f的最小费用流 //如果不能再增广则返回-1 int min_cost_flow(int V,int s,int t,int f) { int res=0; fill(h,h+V,0); while(f>0) { priority_queue<P, vector<P>, greater<P> >que; fill(dis,dis+V,inf); dis[s]=0; que.push(P(0,s)); while(!que.empty()) { P p=que.top(); que.pop(); int v=p.second; if(dis[v]<p.first)continue; for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]) { dis[e.to]=dis[v]+e.cost+h[v]-h[e.to]; prevv[e.to]=v; preve[e.to]=i; que.push(P(dis[e.to],e.to)); } } } if(dis[t]==inf)return -1; for(int i=0;i<V;i++) { h[i]+=dis[i]; } int d=f; for(int i=t;i!=s;i=prevv[i]) { d=min(d,G[prevv[i]][preve[i]].cap); } f-=d; res+=d*h[t]; for(int i=t;i!=s;i=prevv[i]) { edge &e=G[prevv[i]][preve[i]]; e.cap-=d; G[i][e.rev].cap+=d; } } return res; } int main() { int n,k; cin>>n>>k; int s1,t1,f1; int x,y,z,l; for(int i=0;i<k;i++) { cin>>x>>y>>z>>l; add_edge(x,y,z,l); } cin>>s1>>t1>>f1; cout<<min_cost_flow(n,s1,t1,f1)<<endl; return 0; }
标签:距离 分享 false amp i++ 反向 span stream 建图
原文地址:https://www.cnblogs.com/huangzzz/p/9458709.html