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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[ZJOI2010]网络扩容[网络流24题]

發(fā)布時(shí)間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [ZJOI2010]网络扩容[网络流24题] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

[ZJOI2010]網(wǎng)絡(luò)擴(kuò)容[網(wǎng)絡(luò)流24題]

題意:

給定一張有向圖,每條邊都有一個(gè)容量 c 和一個(gè)擴(kuò)容費(fèi)用 w。這里擴(kuò)容費(fèi)用是指將容量擴(kuò)大 1 所需的費(fèi)用。求:

  • 在不擴(kuò)容的情況下,1 到 n 的最大流;

  • 將 1 到 n 的最大流增加 k 所需的最小擴(kuò)容費(fèi)用

  • 題解:

    第一問好說就是跑最大流,關(guān)鍵是第二問怎么想
    兩個(gè)方法:
    其實(shí)本質(zhì)也是一個(gè),我們可以將擴(kuò)容的費(fèi)用轉(zhuǎn)化為增加一點(diǎn)流量,花費(fèi)W的費(fèi)用,因?yàn)槲覀円屬M(fèi)用盡可能低,所以問題就成了最小費(fèi)用流的模型
    如何建圖呢?
    我們可以在第一問的基礎(chǔ)上繼續(xù)建圖,也可以重新建圖(個(gè)人傾向第一種)
    如果是第一種,我們在跑完最大流后,利用殘余網(wǎng)絡(luò)繼續(xù)建圖,(第一問建圖中每條弧的費(fèi)用都是0的),我們再在第i條弧的兩端之間建一條弧,弧的容量為INF,費(fèi)用是cost[i],這樣保證費(fèi)用是最低的
    但是題目要求是增加k,怎么能控制這個(gè)量呢?我們只需要在建立一個(gè)超級源點(diǎn)或者超級匯點(diǎn)(建立一個(gè)即可),連接S(T),容量為K,費(fèi)用為0,也就是我們限制流入量或者流出量最多為K即可

    代碼:

    調(diào)了半天,終于寫出來了。。。。
    注意cnt要從1開始
    因?yàn)?和1是一對相反邊,2和3是一對。。。

    #include<bits/stdc++.h> #define inf 0x3f3f3f #define mem(x,a) memset(x,a,sizeof(x)) typedef long long ll; using namespace std; inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } int n,m,k; int S,T,cnt=1; const int maxn=1e6+9; struct node{int u,v,w,cost,next; }edge[maxn]; int head[maxn],dis[maxn],uu[maxn],vv[maxn],ww[maxn];inline void add_edge(int u,int v,int w,int dis) {edge[++cnt].next=head[u];edge[cnt].u=u;edge[cnt].v=v;edge[cnt].w=w;edge[cnt].cost=dis;head[u]=cnt; } void add(int u,int v,int w,int dis) {add_edge(u,v,w,dis);add_edge(v,u,0,-dis); } int level[maxn]; bool makelevel(int s,int t) {queue<int>q;q.push(s);mem(level,0);level[s]=1;while(!q.empty()){int u=q.front();q.pop(); // if(u==t)return 1;for(int i=head[u];i;i=edge[i].next){int v=edge[i].v;int w=edge[i].w;if(level[v]==0&&w!=0){level[v]=level[u]+1;q.push(v);}}}return level[t]; // return level[t]; } int dfs(int u,int flow,int t) {if(u==t)return flow;int sum=0;for(int i=head[u];i;i=edge[i].next){int v=edge[i].v;int w=edge[i].w;if(level[v]==level[u]+1&&w!=0){int tmp=dfs(v,min(flow-sum,w),t);edge[i].w-=tmp;edge[i^1].w+=tmp;sum+=tmp;if(sum==flow)return sum;}}return sum; } int dinic() {int ans=0;while(makelevel(S,T)){ans+=dfs(S,inf,T);}return ans; } int fa[maxn],vis[maxn],xb[maxn],flow[maxn]; inline bool spfa(int s,int t) {memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));queue<int> q;while(!q.empty())q.pop();mem(fa,-1);vis[s]=1;dis[s]=0;fa[s]=0;flow[s]=inf;q.push(s);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].v;if(edge[i].w>0&&dis[v]>dis[u]+edge[i].cost){dis[v]=dis[u]+edge[i].cost;fa[v]=u;xb[v]=i;flow[v]=min(flow[u],edge[i].w);if(!vis[v]){vis[v]=1,q.push(v);}}}}return fa[t]!=-1; } inline int mcmf(int s,int t) {int sum=0;while(spfa(s,t)){int k=t;while(k!=s){edge[xb[k]].w-=flow[t];edge[xb[k]^1].w+=flow[t];k=fa[k];} // tot+=flow[t];sum+=flow[t]*dis[t];}return sum; } int main() {cin>>n>>m>>k;S=1;T=n;for(int i=1;i<=m;i++){int u,v,w;cin>>uu[i]>>vv[i]>>ww[i]>>dis[i];add(uu[i],vv[i],ww[i],0);} // add(S,1,inf,0); // add(n,T,inf,0);cout<<dinic()<<" ";for(int i=1;i<=m;i++){add(uu[i],vv[i],inf,dis[i]);}add(0,1,k,0);cout<<mcmf(0,n);}

    總結(jié)

    以上是生活随笔為你收集整理的[ZJOI2010]网络扩容[网络流24题]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。