題目鏈結(洛谷 p2762)
w 教授正在為國家航天中心計畫一系列的太空飛行。每次太空飛行可進行一系列商業性實驗而獲取利潤。現已確定了乙個可供選擇的實驗集合\(e = \\),和進行這些實驗需要使用的全部儀器的集合\(i = \\)。實驗\(e_j\)需要用到的儀器是\(i\)的子集\(r_j \subseteq i\)。
配置儀器\(i_k\)的費用為\(c_k\)美元。實驗\(e_j\)的贊助商已同意為該實驗結果支付\(p_j\)美元。w 教授的任務是找出乙個有效演算法,確定在一次太空飛行中要進行哪些實驗並因此而配置哪些儀器才能使太空飛行的淨收益最大。這裡淨收益是指進行實驗所獲得的全部收入與配置儀器的全部費用的差額。
對於給定的實驗和儀器配置情況,程式設計找出淨收益最大的試驗計畫。
本題的正解是最小割。這裡先引用一下ssl_xxy_blackcloud大佬的題解,然後我再具體說明一下:
這道題無非是讓我們權衡獎金與代價,這兩者是有我沒他的,怎麼去處理呢,我們先建立一張圖,所有的實驗與源點相連,容量為其獎金,所有的器材與匯點相連,容量為其**,中間實驗與器材相連,容量為無窮大。一扶蘇一大佬講到,這個問題抽象一下,是這樣的:這個時候跑最小割,其必定會割掉連線實驗或容器的邊,因為中間的邊的代價為無窮大,一定不會被割掉。
跑最小割相當於選擇部分的實驗和部分的儀器,剩下的實驗和儀器就會被割掉,此時再用實驗的總價值減去可能得到的最大值,即為其所要求的答案
如下圖 :
給定乙個有向圖,點有點權,選擇乙個子圖,滿足子圖上如果選擇了乙個點就必須選擇它後繼的所有點。最大化點權和。上面說的有點抽象,下面我結合本題的條件說一說為什麼可以這樣做:這是乙個經典的網路流問題,如果乙個點被選擇了則後繼必須被選擇,那麼稱該圖是閉合的,因此該問題叫做最大權閉合子圖問題。可以使用最小割解決。
建圖的方式就參考ssl_xxy_blackcloud大佬的題解的連線方式。
首先,最小割割掉的肯定要麼是源點連向實驗的邊(以下簡稱左側邊),要麼是儀器連向匯點的邊(以下簡稱右側邊)。我們先考慮第一次割邊。如果被割掉的是左側邊,那麼,我們可以理解為,選擇此次試驗的收益小於成本。反之,如果被割掉的都是右側邊,我們可以理解為,此次試驗的收益大於成本。此時流的大小就是我們付出的成本。
我們這樣理解成本(一定要理解成本,理解了成本,這道題就變成板題了):上面提到的答案是所有試驗的總價值(注意不是利潤)減去最大流(也就是最小割)。也就是說,我們做減法之前,我們只考慮了所有試驗的收入,一點也沒有考慮支出。那麼:
然後,我們考慮後續割邊。我們知道,可以有多場試驗對應相同的儀器。那麼此時,由於儀器連向匯點的邊容量一定是儀器的成本,它只能跑一次,源點連向實驗的邊同理。這就保證了:
如果多場試驗的收入大於這些試驗需要儀器的成本,實驗儀器的成本只記一次。同時,因為多長試驗的收入大於儀器的成本,那麼這些儀器到匯點的邊一定都是滿流量。
如果多場試驗的收入少於這些實驗儀器的成本,那麼一定是源點到這些試驗的邊滿流量,而這些儀器到匯點的邊不是滿流量的。這保證了我們的成本一定是不做這些試驗,而且每場實驗的成本也只記錄一次。
所以,本題的答案就是實驗的總價值(總收入)減去最大流(總成本)。
#include #include #include #include #include #define root 0
#define target 104
using namespace std;
const int maxn = 105;
const int inf = 0x3f3f3f3f;
int n, m, x, ans;
struct edge e[maxn * maxn * 2];
int numedge, head[maxn], depth[maxn], len_s;
char str[10000];
inline void addedge(int from, int to, int val)
int readint (int &cur, char *ch)
while (ch[cur] >= '0' && ch[cur] <= '9')
return x;
}inline bool bfs() }}
return depth[target] != 0;
}int dfs(int u, int flow) }}
return 0;
}int dinic()
}return res;
}int main()
}for (int i = 1; i <= m; i++)
ans -= dinic();
for (int i = 1; i <= n; i++)
if (depth[i] > 0) printf("%d ", i);
putchar('\n');
for (int i = 1; i <= m; i++)
if (depth[i + n] > 0) printf("%d ", i);
printf("\n%d\n", ans);
return 0;
}
最後輸出的地方可能有點迷。我稍微解釋一下:
上述**是用的dinic演算法。首先,題目保證了這是乙個二分圖。所以,在最後一次dfs執行結束後,所有該割掉的邊流量已經都滿了。
但是,此時仍然會額外跑一次bfs。依照**中bfs的規則:
所以,輸出此次bfs掃到的點,就是答案(別把超級源點輸出了)。
網路流24題2 太空飛行計畫問題
w 教授正在為國家航天中心計畫一系列的太空飛行。每次太空飛行可進行一系列商業性實驗而獲取利潤。現已確定了乙個可供選擇的實驗集合 e 和進行這些實驗需要使用的全部儀器的集合 i 實驗 e j 需要用到的儀器是 i 的子集 r j i。配置儀器 i k 的費用為 c k 美元。實驗 e j 的贊助商已同...
網路流24題 太空飛行計畫問題
網路流24題大多需要spj,所以需要乙個有spj的oj,本系列 均在www.oj.swust.edu.cn測試通過 最大權閉合子圖裸題,先將所有收益加起來,源點向每個方案連線一條收益的流,每個方案向對應需要的儀器連一條inf,每個儀器向匯點連一條花費的流。輸出方案只需要在最後的阻塞流中看還剩哪幾個點...
網路流24題 太空飛行計畫問題
已確定了乙個可供選擇的實驗集合e 和實驗需要使用的全部儀器的集合i 實驗ej需要用到的儀器是i的子集rj i。配置儀器ik的費用為ck美元。實驗ej的贊助商已同意為該實驗結果支付pj美元。w教授的任務是找出乙個有效演算法,確定在一次太空飛行中要進行哪些實驗並因此而配置哪些儀器才能使太空飛行的淨收益最...