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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

二分图匹配(一)

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二分图匹配(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 什么是二分圖:
  • 例題:
    • NC111768 CF741C
      • 題目描述:
      • 題解:
      • 代碼:
  • 二分圖最大匹配
    • 匈牙利算法
      • 算法思想:
      • 代碼:
    • K?nig定理
  • 二分圖最優匹配
    • KM(Kuhn-Munkres)算法
      • 算法思路:
      • 具體操作
      • 代碼:
      • 復雜度
    • 代碼:

什么是二分圖:

二分圖充分必要條件條件:
至少有兩個頂點且沒有奇環

二分圖判斷:
通過黑白染色

例題:

NC111768 CF741C

題目描述:

有n對情侶(2n個人)圍成一圈坐在桌子邊上,每個人占據一個位子,要求情侶不能吃同一
種食物,并且桌子上相鄰的三個人的食物必須有兩個人是不同的,只有兩種食物(1或者是2),問一種可行分配方式。

題解:

如果我們能把不能吃同一種食物的人連邊,問題就變成二分圖黑白染色
? 所以情侶關系等價于兩者之間連一條邊
? “每連續的三個人不能都一樣”怎么辦?
? 讓第2i個人和第2i+1個人不能吃一樣的食物即可(即1連2,3連4,5連6以此類推)
? 這樣肯定是個二分圖——2i和2i-1分別連了他兩的情侶,情侶又分別連他兩的一個鄰居……
每次都是給這個可能存在的環加兩個點,所以有環就一定不是奇環

構造方法如下:首先情侶連邊,然后在原圖的相鄰點對上,隔一對連一條邊

代碼:

二分圖最大匹配

促成更多的點配對

匈牙利算法

有一場宴會,男孩和女孩組成舞伴,并且他們必須互相喜歡才能成為舞伴,一個男孩可能喜歡0個或多個女孩,一個女孩也可能喜歡0個或多個男孩,但一個男孩和他喜歡地女孩成為舞伴之后就不能和其他他喜歡地女孩成為舞伴,女孩亦是如此。請問最多可以有多少對舞伴。

算法思想:

對于一個男孩子x,如果他喜歡女孩y,且y還沒有舞伴——讓他們配對
? 如果y有了舞伴,x還是會去嘗試邀請y,如果y發現她的舞伴z可以換一個舞伴,y就主動拋棄掉z(在確定z可以和別人牽手之后),和x成為舞伴

增廣路(交錯路)
路徑的起點和終點都是還沒有匹配過的點,并且路徑經過的連線是一條沒被匹配、一條已經匹配過,再下一條又沒匹配這樣交替地出現。找到這樣的路徑后,顯然路徑里沒被匹配的連線比已經匹配了的連線多一條,于是修改匹配圖,把路徑里所有匹配過的連線去掉匹配關系,把沒有匹配的連線變成匹配的,這樣匹配數就比原來多1個。

代碼:

時間復雜度:
鄰接矩陣O(n^3)
鄰接表:O(n*m)

bool dfs(int x) {for(int i=1;i<=n;i++)//遍歷女生 {if(!a[x][i]||vis[i])continue;//沒連線或者已被找過 vis[i]=1;if(link[i]==0||dfs(link[i]))//link[i]表示第i個女生的男伴是誰 {link[i]=x;return 1;}}return 0; }int main() {for(int i=1;i<=n;i++)//遍歷男生 {memset(vis,0,sizeof(vis));//vis[i]第i個女生在這次找搭檔的過程中被邀請 sum+=dfs(i);} }

K?nig定理

二分圖中最大匹配數等于這個圖中的最小點覆蓋數

最小點覆蓋:
每個點覆蓋以它為端點的所有邊,選擇最少的點來覆蓋所有的邊
(選最少的人,聯系到其他的所有的人)
證明:
視頻時間:01:03:42

二分圖最優匹配

存在邊權,問最大匹配下的最大邊權

KM(Kuhn-Munkres)算法

最優匹配是建立在完美匹配的基礎上的,如果不存在完美匹配,那么本算法失效(但是,我們可以人為連一些權值為0的邊,甚至加點,使得沒有匹配的節點們最后都有一個“虛假”的匹配)。

算法思路:

最開始將每個左邊節點連的權值最大的邊視為有效邊,在匹配給過程當中如果某個點找不到匹配點,則選擇將一些無效邊改成有效邊繼續去匹配,選擇的這些無效邊其實是換掉的原來的某條有效邊,那么我們肯定選換掉的代價最小的。
先讓所有人選最佳搭檔,當發生沖突時,讓降低標準最少的人來換搭檔

具體操作

給每個點預設一個頂標,只有兩個端點的頂標加起來等于邊權的邊,我們才認為是有效邊,
即L[x]+R[y]==w[x][y]的時候才是有效邊
? 最開始左集合的每個點的頂標為他連出去權值最大的邊的權值,右集合每個點頂標為0,當匹配失敗的時候,我們遍歷之前的左集合本次嘗試匹配遍歷過的點,在他們的連向右集合未遍歷的點的邊中找一個與頂標和差值最小的邊,即delta=w[x][y]-L[x]-R[y]最小的邊(可理解為找出一條損失最小的找出一條增廣路。)找到之后修改頂標:左側所有遍歷過的點減去
delta,右邊所有遍歷過的點加上delta,這樣原來的有效邊還是有效邊,而我們新加的邊也已經加上了。
? 重復找匹配+修改頂標的操作,一直到找到一個完美匹配即可

詳細過程:
降低的標準x,左邊-x,右邊+x

每個人都要為了團隊犧牲自己,甘愿降低標準

代碼:

lx[]//左端點,賦值為0x7f ly[]//右端點,賦值為0 link[i]=j//第i個人匹配的是j int dfs(int x) {visx[x]=1; for(int i=1;i<=m;i++){if(!visy[i]&&lx[x]+ly[i]==w[x][i])//有邊且為有效邊 {visy[i]=1;if(link[i]==-1||dfs(link[i])){link[i]=t;return 1;}}}return 0; } memset(ly,0,sizeof(ly)); memset(lx,0xf7,sizeof(lx)); memset(link,-1,sizeof(link)); for(int i=1;i<=n;i++) {for(int j=1;j<=n;j++){lx[i]=max(w[i][j],lx[i]);//最心動的邊 } } for(int i=1;i<=n;i++) {while(1)//全部找到完匹配才能結束 {memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(i))break;//已經給第i人找到匹配int d=0x7f7f7f7f; for(int j=1;j<=n;j++){if(visx[j])//要降低標準的男生 {for(int k=1;k<=m;k++) {if(!visy[k])//引入新的女生 d=min(d,lx[j]+ly[k]-w[j][k]);//求最小的代價 }}}for(d==0x7f7f7f7f)return -1;//匹配失敗 for(int j=1;j<=n;j++)if(visx[j])lx[j]-=d;for(int j=1;j<=m;j++)if(visy[j])ly[j]+=d;} } //n<=m //保證所有男生都匹配(左點),女生不一定

復雜度


·如果卡n^2*m可以用網絡流來做

代碼:

#include<iostream> #include<cstdio> #include<algorithm> #define N 505 #define M 250005 #define INF 9990365505 #define ll long long using namespace std; int n,m,x,y,z,tot,tim,l,r,q[N],fr[N],nxt[M],d1[M],d2[M]; int pre[N],visx[N],visy[N],mchx[N],mchy[N]; ll ex[N],ey[N],slack[N]; void add(int x,int y,int z) {tot++;d1[tot]=y;d2[tot]=z;nxt[tot]=fr[x];fr[x]=tot; } void modify(int cur) {for (int x=cur,lst;x;x=lst)lst=mchx[pre[x]],mchx[pre[x]]=x,mchy[x]=pre[x]; } void bfs(int cur) {for (int i=1;i<=n;i++)slack[i]=INF,pre[i]=0;l=1,r=0;q[++r]=cur;++tim;for (;;){while (l<=r){int u=q[l];l++;visx[u]=tim;for (int i=fr[u];i;i=nxt[i]){int v=d1[i],cost=d2[i];if (visy[v]==tim)continue;ll del=ex[u]+ey[v]-cost;if (del<slack[v]){slack[v]=del;pre[v]=u;if (!del){visy[v]=tim;if (!mchy[v]){modify(v);return;}q[++r]=mchy[v];}}}}ll del=INF;for (int i=1;i<=n;i++)if (visy[i]!=tim)del=min(del,slack[i]);l=1,r=0;for (int i=1;i<=n;i++){if (visx[i]==tim)ex[i]-=del;if (visy[i]==tim)ey[i]+=del; elseslack[i]-=del;}for (int i=1;i<=n;i++)if (visy[i]!=tim && !slack[i]){visy[i]=tim;if (!mchy[i]){modify(i);return;}q[++r]=mchy[i];}} } void KM() {for (int i=1;i<=n;i++)bfs(i);ll ans=0;for (int i=1;i<=n;i++)ans+=ex[i]+ey[i];printf("%lld\n",ans);for (int i=1;i<=n;i++)printf("%d ",mchy[i]);putchar('\n'); } int main() {scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)ex[i]=-INF,ey[i]=0;for (int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);add(x,y,z);ex[x]=max(ex[x],(ll)z);}KM();return 0; }

總結

以上是生活随笔為你收集整理的二分图匹配(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日韩欧美视频一区 | xxxx在线播放 | 小柔好湿好紧太爽了国产网址 | 欧美精品一级在线观看 | 国产成人精品免高潮费视频 | 毛片xxx| 热久久在线 | 总裁边开会边做小娇妻h | 清纯唯美亚洲综合 | 亚洲第一天堂在线观看 | 国产crm系统91在线 | 国产精品毛片久久久 | 黄色av网页| 国产精品成人自拍 | 亚洲视频二| 国产伦理一区 | 国产免费视频一区二区三区 | 日韩电影观看 | 日韩在线一区二区三区四区 | 泽村玲子av | 国产成人自拍视频在线 | 亚洲AV成人无码久久精品同性 | 国模一区二区 | 成人动漫av在线 | www网站在线观看 | 国产一级视频在线 | 国产91熟女高潮一区二区 | 亚洲天堂成人网 | 日本综合视频 | 殴美性生活 | 日韩三级黄色片 | 中文字幕h| 91久久久久国产一区二区 | 国产乱码一区 | 久久精品国产亚洲av高清色欲 | 黄色av网站网址 | 亚洲视频一区二区在线观看 | 欧美福利在线视频 | 成人欧美一区二区三区黑人动态图 | 欧美区一区二 | 香蕉久久夜色精品 | 午夜日韩视频 | 亚洲黄网站在线观看 | 色五夜 | 日韩欧美中文在线 | 精品国产一区二区三区在线 | 伊人黄网 | 亚洲国产精品一区二区三区 | 四虎影院在线看 | 国产黄在线播放 | 色综合中文网 | 欧美精品国产一区二区 | 国产精品久久久精品三级 | 伊人影院在线播放 | 亚洲视频一二三区 | 亚洲AV无码成人片在线观看 | 亚洲精品成人在线视频 | 亚洲永久av| 亚洲成人高清 | 国产情侣久久久久aⅴ免费 caoporn成人 | 亚洲男人网 | 5566在线| 国产一级片免费在线观看 | 日韩在线视 | 亚洲国产一区二区在线观看 | 国产午夜精品理论片 | 亚洲男人在线 | 91麻豆国产福利精品 | 中文字幕精品一区二 | 毛利兰被扒开腿做同人漫画 | 美国一级特黄 | 欧美色涩在线第一页 | 解开乳罩喂领导吃奶 | 男人看的网站 | 日韩精品影院 | 一卡二卡三卡四卡五卡 | 在线观看视频色 | 青娱乐激情| 中国新婚夫妻性猛交 | 丰满人妻一区二区三区46 | 国产情侣av自拍 | 黄色片网站免费在线观看 | 最黄一级片 | 欧美在线一区二区 | 免费黄av| 免费毛片在线播放免费 | 红桃视频一区 | 国产成人在线精品 | 成人午夜天 | 日韩免费看 | 草色网| 久久久久久久久久久综合 | 九九资源网 | 黄色岛国片 | 久热久操 | 激情av小说 | 日本欧美不卡 | 国产高清视频在线 | 天天射天天干天天舔 |