日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ5251:[九省联考2018]劈配——题解

發布時間:2025/3/15 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ5251:[九省联考2018]劈配——题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://www.lydsy.com/JudgeOnline/problem.php?id=5251

https://loj.ac/problem/2477? <-可以看數據

https://www.luogu.org/problemnew/show/P4382

題面太長,請自行讀完之后再看本題。

?

考試的時候讓我傷心的一道題,分明想的就是正解結果sb般第二問沒二分丟了15分

如果b=1就是一個顯然的匈牙利匹配了。

考慮b!=1也只不過就是讓一個導師可以多匹配幾個人而已,額外記錄這個導師是否還能匹配人即可。

那么對于第一問顯而易見匈牙利算法即可完成,復雜度最差就是每個人的其中一個志愿被我們遍歷一遍,于是一次匈牙利是O(n*c),總共O(n^2*c)。

第二問二分答案后對這個點再匈牙利一次,實際就是清出答案和現在這個點之間的點的所有答案,而且我們已經知道了它之前的所有人的志愿和導師選擇,因此大可以直接復制下來而不用重新跑一遍。

因此是O(n^2*logn*c)輕松跑過。

(至于為什么debug這么久純粹是因為我傻,沒有考慮匈牙利算法可以增廣的不只有它前面的點,還可以有后面的點。)

總結:一道好題,洛谷評分虛高,實際為省選/NOI-,但是為了紀念我debug的時間之長,于是評了個NOI。

#include<cmath> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<iostream> using namespace std; const int N=210; inline int read(){int X=0,w=1;char ch=0;while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')X=(X<<1)+(X<<3)+ch-'0',ch=getchar();return X*w; } int n,m,b[N],bb[N],s[N]; int ds[N],zy[N],dds[N],zzy[N]; int a[N][N][11],len[N][N]; bool vis[N]; bool dfs(int k,int w){for(int j=1;j<=len[k][w];j++){int u=a[k][w][j];if(vis[u])continue;vis[u]=1;if(b[u]){ds[k]=u;zy[k]=w;b[u]--;return 1;}else{for(int l=1;l<=n;l++){//這里debug 3h+才發現。 if(l==k)continue;if(ds[l]==u){if(dfs(l,zy[l])){ds[k]=u;zy[k]=w;return 1;}}}}}return 0; } inline void copy(int k){for(int i=1;i<=m;i++)b[i]=bb[i];for(int i=1;i<=k;i++){ds[i]=dds[i];zy[i]=zzy[i];b[ds[i]]--;}for(int i=k+1;i<=n;i++)ds[i]=-1;return; } inline void work2(){for(int i=1;i<=n;i++){if(zzy[i]<=s[i])printf("0 ");else{int l=1,r=i-1,ans=0;while(l<=r){int mid=(l+r)>>1;bool ok=0;copy(mid-1);memset(vis,0,sizeof(vis));for(int j=1;j<=s[i];j++){if(dfs(i,j)){ans=mid;l=mid+1;ok=1;break;}}if(!ok)r=mid-1;}printf("%d ",i-ans);}}puts(""); } inline void work1(){for(int i=1;i<=n;i++){memset(vis,0,sizeof(vis));for(int j=1;j<=m;j++){if(!len[i][j])continue;if(dfs(i,j))break;}}for(int i=1;i<=n;i++){zzy[i]=zy[i];dds[i]=ds[i];printf("%d ",zy[i]);}puts(""); } inline void init(){n=read(),m=read();memset(len,0,sizeof(len));for(int i=1;i<=m;i++)bb[i]=b[i]=read();for(int i=1;i<=n;i++){zy[i]=m+1;ds[i]=-1;for(int j=1;j<=m;j++){int k=read();if(k)a[i][k][++len[i][k]]=j;}}for(int i=1;i<=n;i++)s[i]=read(); } int main(){int t=read(),c=read();while(t--){init();work1();work2();}return 0; }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

轉載于:https://www.cnblogs.com/luyouqi233/p/8764623.html

總結

以上是生活随笔為你收集整理的BZOJ5251:[九省联考2018]劈配——题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。