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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

HDU - 3551 Hard Problem(一般图最大匹配)

發布時間:2024/4/11 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 3551 Hard Problem(一般图最大匹配) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一張無向圖,問能否刪除任意數量的邊,使得每個點的度數都達到指定的數值

題目分析:參考博客:https://www.cnblogs.com/xiongtao/p/11189452.html

很巧妙的建圖,需要拆度+拆邊建圖,如第一個樣例而言:

4 4

1 2

3 4

2 3

1 4

1 2 1 0

建圖為:

?點 1 代表節點 1 的一個度,點 2 和點 3 代表節點 2 的一個度,點 4 代表節點 3 的一個度

剩下的結點 5 ~ 節點 12 都是對每條邊的拆點

對于每條邊而言,只需要將相應的 度拆點 都連好就ok了,建好圖后跑一般圖的最大匹配,如果每個點都能恰好匹配的話,那么答案就是 yes 了

大概解釋如下,對于每條邊而言,最大匹配只有兩種情況,第一種是,兩端的度拆點分別和兩個邊拆點被匹配,這樣代表了這條邊需要留在原圖中,也就是需要被使用,另一種情況是只有邊拆點的兩個點被匹配,代表著這條邊在原圖中應該被刪除

實現就比較簡單了

代碼:
?

#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e3+100;const int M=N*N*2;int x[N],y[N],du[N],id[N][N];int n,m,que[M],ql,qr,pre[N],tim=0;struct edge {int v,nxt; }e[M];int h[N],tot=0;int match[N],f[N],tp[N],tic[N];int find(int x) {return f[x]==x?f[x]:f[x]=find(f[x]); }void addedge(int u,int v) {e[++tot]=(edge){v,h[u]};h[u]=tot; }int lca(int x,int y) {for (++tim;;swap(x,y)) if(x) {x=find(x);if(tic[x]==tim) return x; else {tic[x]=tim;x=pre[match[x]];}} }void shrink(int x,int y,int p) {while(find(x)!=p) {pre[x]=y;y=match[x];if(tp[y]==2) {tp[y]=1;que[++qr]=y;}if(find(x)==x) f[x]=p;if(find(y)==y) f[y]=p;x=pre[y];} }bool aug(int s) {for(int i=1;i<=n;++i) f[i]=i;memset(tp,0,sizeof tp);memset(pre,0,sizeof pre);tp[que[ql=qr=1]=s]=1; // 1: type A ; 2: type Bint t=0;while(ql<=qr) {int x=que[ql++];for(int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {if(find(v)==find(x)||tp[v]==2) continue; if(!tp[v]) {tp[v]=2;pre[v]=x;if(!match[v]) {for(int now=v,last,tmp;now;now=last) {last=match[tmp=pre[now]];match[now]=tmp,match[tmp]=now;}return true;} tp[match[v]]=1,que[++qr]=match[v];} else if(tp[v]==1) {int l=lca(x,v);shrink(x,v,l);shrink(v,x,l);}}} return false; }int solve() {int ans=0;for(int i=1;i<=n;i++)if(!match[i]&&aug(i))ans++;return ans; }void init() {tot=0;memset(id,0,sizeof(id));memset(match,0,sizeof(match));memset(tic,0,sizeof(tic));memset(h,0,sizeof(h)); }void build() {int cnt=0;for(int i=1;i<=n;i++)for(int j=1;j<=du[i];j++)id[i][j]=++cnt;for(int i=1;i<=m;i++){addedge(cnt+1,cnt+2);addedge(cnt+2,cnt+1);for(int j=1;j<=du[x[i]];j++){addedge(id[x[i]][j],cnt+1);addedge(cnt+1,id[x[i]][j]);}for(int j=1;j<=du[y[i]];j++){addedge(cnt+2,id[y[i]][j]);addedge(id[y[i]][j],cnt+2);}cnt+=2;}n=cnt; }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){init();scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d",x+i,y+i);for(int i=1;i<=n;i++)scanf("%d",du+i);build();if(solve()*2==n)printf("Case %d: YES\n",++kase);elseprintf("Case %d: NO\n",++kase);}return 0; }

?

總結

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

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