網路流拆點法和分配結點和超級源點匯點的應用
有F種食物和D種飲料,每種食物或飲料只能供一頭牛享用,且每頭牛隻享用一種食物和一種飲料。現在有n頭牛,每頭牛都有自己喜歡的食物種類列表和飲料種類列表,問最多能使幾頭牛同時享用到自己喜歡的食物和飲料。(1 <= f <= 100, 1 <= d <= 100, 1 <= n <= 100)
一種顯然的想法是所有食物連源點,所有飲料連線匯點,然後讓牛為中間結點,跑一次最大流. 但是這樣會出現一個牛用了多個食物和飲料的情況。
這種情況下我們把牛拆成兩部分(i,N+i)i部分與食物連線,N+i部分與飲料連線,然後兩部分自己連線(流量為1)。這樣跑出來的網路流,保證了每個牛隻有一種分配方案.注意體會飲料,食物,牛之間的編號方法.還有源點匯點的編號.
因為要保證各個點之間不會出現重複的現象,現規定0-N-1是第一部分牛的編號. N-2N-1部分是第二部分牛. 2*N-2*N+f是食物部分 2*N+f-2*N+f+d是飲料部分,不放心的中間自己加點常數啥的
最後源點s=2*n+f+d 匯點t=s+1;
程式碼部分:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#define maxn 500
#define INF 10000000
using namespace std;
struct Edge{
int from,to,cap,flow;
};
struct Dinic{
int n,m,s,t;
vector<Edge> edges;vector<int> G[maxn];
bool vis[maxn];int d[maxn],cur[maxn];
void init(int n){
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
void addedge(int from,int to,int cap){
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0});
m=edges.size();G[from].push_back(m-2);G[to].push_back(m-1);
}
bool bfs(){
memset(vis,0,sizeof(vis));
queue<int> Q;Q.push(s);vis[s]=1;d[s]=0;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=0;i<G[x].size();i++){
Edge &e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
} return vis[t];
}
int dfs(int x,int a){
if(x==t||a==0) return a;
int flow=0,f;
for(int &i=cur[x];i<G[x].size();i++){
Edge &e=edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
e.flow+=f;edges[G[x][i]^1].flow-=f;
a-=f;flow+=f;
if(a==0) break;
}
} return flow;
}
int Max_flow(int s,int t){
this->s=s;this->t=t;
int flow=0;
while(bfs()){
memset(cur,0,sizeof(cur));flow+=dfs(s,INF);
} return flow;
}
};int lf[105][105],ld[105][105];
int main(){ int N,F,D,i,j,k,food,drink,temp;cin>>N>>F>>D;
Dinic dd;memset(lf,0,sizeof(lf));memset(ld,0,sizeof(ld));
for(i=0;i<N;i++){
scanf("%d%d",&food,&drink);
while(food--){ scanf("%d",&temp);lf[i][temp-1]=1;
}
while(drink--){ scanf("%d",&temp);ld[i][temp-1]=1;
}
} //foodnumber=2*N+i drinknumber=2*N+f+i
int s=2*N+F+D+20; int t=s+1;
for(i=0;i<F;i++){
dd.addedge(s,2*N+i,1); // link food to s
}
for(i=0;i<D;i++){
dd.addedge(2*N+i+F,t,1); //t to drink
}
for(i=0;i<N;i++){
dd.addedge(i,N+i,1); //cow to cow
for(j=0;j<F;j++) {
if(lf[i][j]) dd.addedge(2*N+j,i,1); // food to cow
}
for(j=0;j<D;j++){
if(ld[i][j]) dd.addedge(N+i,2*N+F+j,1); //cow to drink
}
}
printf("%d\n",dd.Max_flow(s,t));
return 0;}
相關文章
- Hbase和Hive的特點,和應用場景Hive
- java處理流 和節點流(在位元組流和字元流中,又分為處理流和節點流)Java字元
- vue和react的相同點和不同點VueReact
- MySQL垂直拆分和水平拆分的優缺點和共同點總結MySql
- 物理安全和網路安全的交點在哪?
- 多點對多點網路模式的網路特徵模式特徵
- 繼承的優點和缺點繼承
- 節點的運用和方法
- 實時熱點網站有哪些?3個超實用的熱點網站,輕鬆找熱點網站
- Android應用安全防護的點點滴滴Android
- 索引表和 ES 的一點點思考索引
- PyLint 的優點、缺點和危險
- 疊層電感的優點和應用gujing
- 四大主流PHP框架的優點和缺點總結PHP框架
- iframe有哪些優點和缺點?
- 物理安全和網路安全的交點在哪裡呢?
- CAN匯流排取樣點測試
- [Kubernetes]node節點pod無法啟動/節點刪除網路重置
- 開源的工作流系統突出優點總結
- 每日一個知識點:Volatile 和 CAS 的弊端之匯流排風暴
- 大資料的結構和特點大資料
- BZOJ 3931 [CQOI2015]網路吞吐量:最大流【拆點】
- 網際網路專案的特點和架構目標架構
- Java單例模式:缺點和優點Java單例模式
- 多層PCB的優點和缺點有哪些?
- Python 中 eval 與 exec 的相同點和不同點Python
- 知識點:樹中結點的度以及葉子結點(度為0的結點)的計算
- 計算機網路王道考研-TCP的特點和TCP首部格式總結計算機網路TCP
- JS物件的方括號表示法和點表示法JS物件
- JaCoCo 企業級應用的優缺點分析
- 不帶頭結點的單連結串列的建立(頭插法和尾插法)
- WebRTC 及點對點網路通訊機制Web
- AR真人大屏互動的應用形式和特點
- GAN原理,優缺點、應用總結
- 拆點判定二分圖
- 盤點:網際網路大廠端午禮盒的優缺點
- ERP系統有哪些優點和缺點?
- 【工業網際網路】工業網際網路平臺建設,出發點、切入點及著力點;