日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P4015 运输问题

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4015 运输问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P4015 運輸問題

文章目錄

    • 題目描述:
    • 輸入格式:
    • 輸出格式:
    • 輸入輸出樣例:
    • 題解:
    • 代碼:

題目描述:

輸入格式:

輸出格式:

兩行分別輸出最小運輸費用和最大運輸費用。

輸入輸出樣例:

輸入 #1

2 3 220 280 170 120 210 77 39 105 150 186 122

輸出 #1

48500 69140

題解:

最小費用最大流(MCMF)問題
根據樣例數據分析:
橙色為第一個倉庫暈倒各零售商店的單位費用
綠色為第二個

一邊是倉庫,一邊是商店,典型的二分圖,還是完全二分圖
我們可以在倉庫的左邊設置一個源點S,右邊設置一個終點T。S指向每一個倉庫,容量為ai,費用為0,而每一個商店指向T,容量為bi,費用為0
從倉庫到商店的邊容量是min(倉庫貨物量ai,商店容量bi),費用為讀入的值
為了方便處理,我們可以將S點記為編號1,倉庫為編號1 ~ m,商店為m+1 ~ n+m,T點為201
然后直接跑最小費用最大流就可以了
找到最大后,將費用取反再跑一遍即可找到最小

代碼:

#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<queue> #include<stack> #include<vector> #include<map> #include<set> #include<algorithm>#define I_copy_this_answer return 0;using namespace std;int n,m,head[1100]; int cnt=1; int mincost,maxwater; int flow[1100]; int b[1100],cost[310][310]; int pre[1100],last[1100],dis[1100],vis[1100],a[1100]; int s=0; //last記錄邊,pre記錄點 struct node{int next,to,dis,flow; }edge[100860]; void addedge(int next,int to,int dis,int flow) {edge[++cnt].to=to;edge[cnt].dis=dis;edge[cnt].flow=flow;edge[cnt].next=head[next];head[next]=cnt; }int spfa() {memset(flow,0x3f,sizeof(flow));memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));queue <int> q;q.push(s);dis[s]=0;vis[s]=1;pre[201]=-1; //初始化匯點的前點 while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];i;i=edge[i].next){int v=edge[i].to;int w=edge[i].dis;int l=edge[i].flow;if(dis[u]+w<dis[v]&&l>0) //沒有流量的話這條路就增廣不了,最短距離是建立在增廣路存在的基礎上的 {dis[v]=dis[u]+w;last[v]=i; //last指的是這個點(v)與上個點(u)相連的邊的編號 pre[v]=u; //pre指的是這條路徑上這個點(v)的上一個點 flow[v]=min(flow[u],l); //把當前邊流量與上個點的流量對比,解決出現倉庫貨物比需要的少的情況 if(!vis[v]){q.push(v);vis[v]=1;}}}}return pre[201]!=-1; //如果不是這個值就說明這個點被刷新,增廣成功 }void mcmf() {while(spfa()){mincost+=dis[201]*flow[201]; //從源點出發到匯點的單位費用再乘以單位,由于每次只增廣一條路,而且倉庫和商店是直接連接的,可以這樣寫 int t=201;while(t!=0){edge[last[t]].flow-=flow[201]; //回溯,修改每條邊的流量,因為該算法中途找到的增廣路不是最后的增廣路,所以這個要等到最后來改變 edge[last[t]^1].flow+=flow[201];t=pre[t];}} }void build_edge(int t)//t用來控制邊權的正負,為了方便求最小和最大 {for(int i=1;i<=m;i++){addedge(0,i,0,a[i]);addedge(i,0,0,0);//與源點S相連 } for(int i=1;i<=m;i++)for(int j=1;j<=n;j++){addedge(i,j+m,cost[i][j]*t,b[j]);addedge(j+m,i,-cost[i][j]*t,0);//倉庫與商店相連 }for(int i=1;i<=n;i++){addedge(i+m,201,0,b[i]);//與匯點T相連 addedge(201,i+m,0,0);} }int main() {int i,j;scanf("%d %d",&m,&n);for(i=1;i<=m;i++){int t1;scanf("%d",&a[i]); }for(i=1;i<=n;i++)scanf("%d",&b[i]);for(i=1;i<=m;i++)for(j=1;j<=n;j++)scanf("%d",&cost[i][j]); //倉庫與商店的邊權 build_edge(1); //建立邊權為正的邊,跑最小費用最大流 mcmf();//最小費用最大流(Min Cost Max Flow )的縮寫 printf("%d",mincost); maxwater=0;mincost=0; cnt=1;memset(head,0,sizeof(head));build_edge(-1);//建立邊權為符的邊 mcmf();printf("\n%d",-mincost); } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的P4015 运输问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。