/*
題目描述:有n種糖果和m個小孩,每個小孩有乙個要求的愉悅度b[i],給出乙個n*m的like矩陣,若like[i][j]=1說明i小孩喜歡j糖果,那麼如果
將j糖果分給i小孩則i小孩將獲得k點愉悅度,若like[i][j] = 0,那麼如果將i糖果分給j小孩,那麼i小孩將獲得1點愉悅度,求問有沒有糖果的分配方
案使得每個小孩都滿足其要求的愉悅度b[i]
方法:使用最小費用最大流解決該問題,圖共分為四列,第一列源節點,第二列糖果,第三列小孩,第四列匯節點;
從源點向每個糖果連一條容量為1,價值為0的邊;
對於每個糖果,如果小孩i喜歡該糖果則從該糖果連向該小孩一條容量為1,價值為0的邊,否則不連;
對於每個小孩,計算sum = b[i]/k , rest = b[i] % k,
若sum!=0,則從小孩向匯點連一條容量為sum,價值-為-k的邊;
若rest!=0,則從小孩向匯點連一條容量為1,價值為-rest的邊;
計算最小費用最大流的流量flow,費用cost,則已產生的愉悅度為-cost,用剩下的糖果能產生的愉悅度為n-flow;
若-cost + n - flow大於等於b[i]之和,輸出yes(注意一定是大於等於,不能是僅僅等於)
順便說一句,最大費用最大流該怎麼求?把每條邊的價值取反就行
*/#include
#include
#include
#include
#include
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int inf = 1000000000;
const int maxn = 100;
int n,m,k;
int b[maxn];
int like[maxn][maxn];
typedef long long ll;
struct edge
;struct mcmf
void addedge(int from,int to,int cap,int cost)
;edge e2 = ;
edges.push_back(e1);
edges.push_back(e2);
int m = edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}bool bellmanford(int s,int t,int &flow , ll& cost)
d[s] = 0; p[s] = 0; a[s] = inf;
mem(inq,0); inq[s] = 1;
queueq;
q.push(s);
while(!q.empty())}}
}if(d[t]==inf) return false;
flow += a[t];
cost += (ll)a[t]*(ll)d[t];
int u = t;
while(u!=s)
return true;
}ll mincost(int s,int t,int & flow) //模板的這裡用&的目的是為了return cost的同時帶回過程中的flow值
};mcmf g;
int main()
for(int j = 1;j<=n;j++)
for(int i = 1;i<=m;i++)}}
for(int i=1;i<=m;i++)
int flow;
ll ans1 = g.mincost(source , sink,flow);
int remain = n - flow;
if(-ans1 + remain >= require)
else
}return 0;
}
hdu 4322 Candy 最大費用最大流
很巧妙的建圖,沒有加成的糖對每個人都是一樣的所以建圖的時候只考慮加成的情況,以糖給人加的點數為費用,乙個人需要的點數為a則建一條由這個人指向匯的容量為a k費用為 k的邊,如果有餘數就再建一條容量為1費用為這個餘數的邊,由源向糖建邊,有加成效果的人和糖的組合之間連線,求這個圖的最小費用最大流即可。d...
hdu 4411 最小費用流
思路 這道題建圖比較難想,首先是建立超級源點和超級匯點,那麼由於有k個警察,於是vs與0連邊,容量為k,費用為0,因為這k個警察不一定都出去,也就是不一定是最大流,於是0和vt連邊,容量為k,費用為0。然後就是拆點建圖了 1 0到i連邊,容量為1,費用0到i的最短路,表示去抓城市i的小偷。2 從i到...
hdu 4411 最小費用流
思路 這道題建圖比較難想,首先是建立超級源點和超級匯點,那麼由於有k個警察,於是vs與0連邊,容量為k,費用為0,因為這k個警察不一定都出去,也就是不一定是最大流,於是0和vt連邊,容量為k,費用為0。然後就是拆點建圖了 1 0到i連邊,容量為1,費用0到i的最短路,表示去抓城市i的小偷。2 從i到...