劈配,匹配,網路流。那麼考慮怎麼跑網路流。
先看第一問。首先套路的建出超源超匯。不用想也知道導師向匯連容量為戰隊人數上限的邊。特別地,給出局也建乙個點,向匯連容量inf的邊(似乎沒有必要)。對於乙個新學員,假設我們已經知道了之前的學員的最優選擇,可以把之前的每名學員和可以選擇的導師連邊,並由源向學員連容量為1的邊。然後對於該名新學員,先只連最優選擇的邊,如果此時跑出的最大流不等於學員數,則表明這名學員無法選擇最優,那麼刪掉最優邊(此時這些邊裡一定沒有流量,可以通過容量改為0實現)並連上次優邊,次優邊還是不行的話繼續,一直這樣下去直到最大流等於學員數。第一問就做完了。至於複雜度,o(能過)。
然後是第二問。對於每個人可以二分答案,然後跑最大流看其是否滿足。似乎需要訪問網路的歷史狀態?可持久化網路流!這玩意似乎沒法可持久化啊……那就暴力記下來唄。由於有c的限制,這裡面的邊不會很多。於是就做完了,o(能過)。還有一種做法是先連上該學員可以選擇的邊,然後從第一名開始依次把最優選擇加進去跑,直到無法滿足,可能會快不少。
#include#include#include
#include
#include
#include
#include
using
namespace
std;
intread()
while (c>='
0'&&c<='
9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}#define n 210
#define s 0
#define t 404
int test,c,n,m,b[n],s[n],p[n<<1
],cnt[n],t;
int cur[n<<1],d[n<<1],q[n<<1
],ans,cho[n];
vector
a[n][n];
struct dataedge[n*n<<2],hisedge[n][2510
];void addedge(int x,int y,int
z)void addedge(int x,int y,int cap,int
flow)
void
init()
a[i][m+1].push_back(m+1
); }
for (int i=1;i<=n;i++) s[i]=read();
}bool
bfs()
}while (headreturn ~d[t];
}int work(int k,int
f)
if (used==0) d[k]=-1
;
return
used;
}void
dinic()
}int
main()
for (int k=tmp+1;k<=t;k+=2) edge[k].cap=0
; }
for (int j=0;j<=t;j+=2
)
if (edge[j].cap) hisedge[i][++cnt[i]]=edge[j],hisedge[i][cnt[i]].nxt=edge[j^1
].to;
}/*for (int i=0;i<=n;i++)
printf(
"%d
",i-add-1
); }
cout
<}
return0;
}
Bzoj5251 線段樹 貪心
bzoj5251 線段樹 貪心 記錄本蒟蒻省選後的第一篇題解 國際慣例的題面 首先這個東西顯然是一棵樹。如果我們把數值排序,並建立這棵樹的dfs序,顯然dfs序上的乙個區間對應數值的乙個區間,且根為數值區間左端點。如果你這樣想,恭喜你能獲得50分,如果記得加了eps會獲得55 60分。因為當數值可以...
八省聯考2018 劈配
題目這題目,乍一眼看上去像乙個dp,因為這個資料範圍一般都是dp,但是考慮到轉移有後效性,所以顯然是做不了dp的。考試的時候像著怎麼設狀態沒有後效性,失敗了,就只打了乙個70分的暴力,還掛了20分。這題其實是個 網路流 匹配 真心看不出,然後我寫部落格的時候旁邊yl神犇看見了,嘲諷了我一波,我是真的...
八省聯考2018 劈配
題解 這題思路就是暴力。主要在於分析複雜度?dinic跑二分圖 msqrt n 這題好像用不到。首先這是個匹配問題顯然需要利用網路流 考慮第一問 每一次我們就暴力按照志願順序加入邊 直到二分圖匹配數 1 這個複雜度是 nm nm 的 因為一次只增廣一條邊所以每次是nm的,不過這個很明顯是跑不滿而且差...