網路流拆點法和分配結點和超級源點匯點的應用
有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;}
相關文章
- 網路流+拆點+sap+uva10330
- 關於《網路安全法》的意義和亮點
- Hbase和Hive的特點,和應用場景Hive
- MySQL垂直拆分和水平拆分的優缺點和共同點總結MySql
- 多點對多點網路模式的網路特徵模式特徵
- 物理安全和網路安全的交點在哪?
- 替代Apache和IIS的輕量級網路伺服器盤點Apache伺服器
- 實時熱點網站有哪些?3個超實用的熱點網站,輕鬆找熱點網站
- 索引表和 ES 的一點點思考索引
- mysql和Oracle的特點,優缺點MySqlOracle
- 抽象類和介面的相同點和不同點抽象
- 四大主流PHP框架的優點和缺點總結PHP框架
- arcgis api for flex求線段的起點,終點和中點APIFlex
- Android應用安全防護的點點滴滴Android
- iOS和Android的點對點連線iOSAndroid
- 和程式設計師約會的優點和缺點程式設計師
- 物理安全和網路安全的交點在哪裡呢?
- 疊層電感的優點和應用gujing
- Java單例模式:缺點和優點Java單例模式
- 大資料的結構和特點大資料
- 常用的開源網路和資料庫監控工具功能和優缺點介紹資料庫
- 查詢熱點快和熱點塊的操作
- 資料庫索引的作用和優點缺點資料庫索引
- 網路學習英文的資源站點蒐集
- rownum和rowid,row_number一點應用
- js難點精解-----原型和原型鏈的關係和應用JS原型
- WebRTC 及點對點網路通訊機制Web
- Java —— 節點流Java
- 讓網頁上的超連結失效,不能點選網頁
- GAN原理,優缺點、應用總結
- JS物件的方括號表示法和點表示法JS物件
- history API 和錨點連結在單頁應用頁面切換中的應用API
- 每日一個知識點:Volatile 和 CAS 的弊端之匯流排風暴
- C# 多執行緒和非同步的相同點和不同點C#執行緒非同步
- 計算機網路王道考研-TCP的特點和TCP首部格式總結計算機網路TCP
- TCP協議要點和難點全解TCP協議
- 全域性檢查點和增量檢查點
- AR真人大屏互動的應用形式和特點