題意: 一共有n 天 每天需要ai個志願者
有m種志願者 每種志願者可以從 第si 天工作到ti 天 每個需要ci元 問花最少的錢滿足每天的需求
顯然是費用流
如果正常連邊的話 每個志願者對其輻射的天非常難處理
可以採用時間軸的連法:
源點連第一天
匯點連最後一天
容量為inf費用為0
這樣跑網路流是沿時間流的(就是依次解決每一天的問題)
然後每一天向後一天連一條容量為inf-a[i]
費用為0的邊
為什麼容量為inf-a[i]
這就相當於少了a[i]
得用帶權邊補全inf
這就是志願者連續乾時沿這條邊跑
因為連續幹不花錢
所以優先選這種邊
然後將每一類志願者s[i]與t[i]+1連一條容量為
inf花費為c[i]的邊
當連續幹的人不夠時
就得使勁往裡塞人
#includeusingview codenamespace
std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ri(n) scanf("%d",&(n))
#define rii(n,m) scanf("%d%d",&n,&m)
#define riii(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define rs(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define clr(a,v) memset(a,v,sizeof a)
/////////////////////////////////
/const
int n=100001
;ll maxflow,mincost;
intlast[n],pre[n],dis[n],flow[n];
bool
vis[n];
struct
edgeedge[n
<<1
];int pos=1
,head[n];
void
init()
queue
q;void add(int
from,int to,int flow,int dis)//
flow流量 dis費用
bool spfa(int s,int
t) }}}
return pre[t]!=-1;}
void mcmf(int s,int
t) }
}int
a,b,s,t,n,m,c,x;
intmain()
s=n+2,t=s+1
; add(s,
1,inf,0);add(n+1,t,inf,0
); mcmf(s,t);
printf(
"%lld\n
",mincost);
return0;
}
洛谷 P3980 NOI2008 志願者招募
我居然現在才會用費用流解線性規劃 當然這裡解決的一類問題比較特殊 以式子作為點,變數作為邊,然後要求就是變數在不同的式子裡出現了兩次,係數一次為 1,一次為 1 這樣的話就作為了乙個出度和乙個入度,和邊正好對應了 我們設每種志願者選擇人數是 x 我們的限制是 left x geq 0 x x geq...
luoguP3980 NOI2008 志願者招募
這道題的難點主要在於處理乙個人可以對區間產生貢獻這個限制。我們之前都是將乙個人當成流量,但是這一容量的流量可以對乙個區間的點產生貢獻,這就導致這個問題無法處理。於是考慮怎麼將乙個點可以對乙個區間產生貢獻在圖上表示出來 我們考慮每一天,從 s 向 1 連容量為 inf 的邊,從 i 向 i 1 連容量...
NOI2008 志願者招聘
文化課 競賽雙廢物又來水題解了。把下界限制轉化為一條邊的流量下界,這樣就是最小費用上下界最大流。加入幾個新值,其條件正好為 ge 0 將其當做一條流量,這樣不等式就變成了等式,我們可以利用流量守恆,用點的流滿 leftrightarrow 等式成立,這樣就變成了乙個最小費用最大流,去掉了上下界的影響...