互補鬆弛定理
xi,yi分別為原問題和對偶問題的最優解,當且僅當
sigma(aij*yi | i=1~m)==cj or xi=0 j=1,2...,n
sigma(aij*xj | j=1~n)==bi or yi=0 i=1,2...m
題意:給乙個n*n
的矩陣,每次可以攻擊一列或者一行,攻擊一行的代價為
ai,攻擊一列的代價為
bi,要求每個格仔
i,j至少被攻擊
f[i][j]
次,要使得總代價最小,同時輸出方案
第一次接觸對偶定理就是這道題,那時候把對偶弄清楚了,但是互補鬆弛定理一直無法理解,不會輸出方案就不了了之了...
就對偶之後的建圖來說,其實比日本那道題要簡單一些
首先先把第一步的對偶定理做好,
建立n+n
個變數,lx1...lxn,ly1...lyn
分別表示每行每列攻擊了幾次
則我們的目標是
min約束條件
lxi+lyj>=f[i][j]
係數矩陣不好畫就自己yy
吧...
對偶之後化為
max約束條件提取
sigma(yi | i=(k-1)*n+1~k*n)<=ak
sigma(yi*n+k | i=1~n)<=bk
然後根據這個建圖
源點連出n
個點,每條邊容量為
ai,費用為0
n個點連向匯點,每條邊容量為
bi,費用為0
中間連n*n
條邊,,容量為
oo,費用為
f[i][j]
然後跑最大費用最大流,就可以了
但是很不爽的就是第二步,題解上講的模糊不清,就說在殘量網路跑一次最長路,根據互補鬆弛定理就可以得解,然後就一直無法理解...
現在重新來看,發現每個不等式至多有兩個變數,也就是說,可以用差分約束系統來做,然後瞬間就豁然開朗了...
先看互補鬆弛定理第乙個條件(我們可以發現網路流中間的n+n
個點都會代表原問題中的乙個變數)
它的意思就是說ai(bi)
流滿或者是
lxi(lyj)為0
然後第二個條件
這條邊沒有流量或者是
lxi+lyj==f[i][j]
同時注意有幾個隱含條件,lxi>=0,lyj>=0,lxi+lyj>=f[i][j]
然後這些式子都至於兩個變數有關,差分約束就很顯然了,
設d[i]=-lxi
就可以建圖了
我的做法是直接重建圖,跑差分約束,但std
貌似確實是直接在殘量網路上跑的,應該是簡化了建圖之類的吧
#include #include #include #include #include const int oo=1073741819;
using namespace std;
int d[20000],tail[20000],p[20000],v[20000],f[500][500],a[500][500];
int next[2000000],cost[2000000],sora[2000000],flow[2000000],po[2000000];
int st[2000000],s,t,n,ss,tot,s1;
bool spfa(int s,int t)
}} v[ne]=0;
} return d[t]>-oo;
}int widen()
tot+=sum;
for (int i=t;i!=s;i=sora[po[p[i]]])
return ans;
}void getans(int s)
}} v[ne]=0;
}// cout<
原始對偶版,直接從1s+進入0.3s(並且最大費用和最小費用只需修改鬆弛條件,越來越搞不懂原始對偶了...)
#include #include #include #include #include const int oo=1073741819;
using namespace std;
int d[20000],tail[20000],p[20000],v[20000],f[500][500],a[500][500];
int next[2000000],cost[2000000],sora[2000000],flow[2000000],po[2000000];
int w_time,st[2000000],s,t,n,ss,tot,s1,phi,flag[200000],ans;
bool spfa(int s,int t)
}} v[ne]=0;
} //cout}
} v[ne]=0; }}
void origin()
void link(int x,int y,int z,int c)
int a[500],b[500];
int main()
for (int i=1;i<=n;i++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
ans=0;
tot=0;
int sum=0;
for (phi=0;spfa(s,t);)
for (int tmp;w_time++,tmp=dfs(s,oo);) {
sum+=tmp;
//cout<
7 5省隊集訓 tree
思路 樹形dp。先求最大值。令s x 為x的子樹中葉子節點的數量。f x 為到x時 為先手走,先手能取到的值在子樹中排第f x 小。g x 為到x時 為後手走,後手能取到的值在子樹中排第f x 小。對f x 先手應該往哪個子樹走呢?對於x的一棵子樹y,如果進入,那麼最終答案就是這棵子樹中第g y 小...
FJOI省隊集訓 florida
省隊成員 大部分 都沒來.像我這種沙茶天天寫寫玄學演算法都能排在榜上面.果然正解寫掛的人遠比暴力拍對的人少啊.陸陸續續會補一些題解。不過有些題太神了可能補不上題解 有n個物品,兩個袋子a和b。若物品i與j放在同乙個袋子裡,那麼代價為t i j 保證t i i 0,t i j t j i 乙個袋子的代...
7 10省隊集訓夢工廠
思路 題面真心長.單調棧維護上凸殼即可 設sum i 為前i道工序的複雜度之和,g i 為第i個快樂最早開始生產的時間。因為我們要保證沒有兩個快樂同時出現在同一道工序,所以 g i g i 1 max sum j f i 1 sum j 1 f i 然後就是像斜率優化的過程了 sum j f i 1...