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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

AT4505-[AGC029F]Construction of a tree【构造题,hall定理,网络流】

發布時間:2023/12/3 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AT4505-[AGC029F]Construction of a tree【构造题,hall定理,网络流】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/AT4505


題目大意

給出nnn個點和n?1n-1n?1個點集UiU_iUi?,每個點集中選擇兩個點連邊使得該圖是一棵樹。求方案。

n∈[1,105],∑i=1n?1∣Ui∣∈[1,2?105]n\in[1,10^5],\sum_{i=1}^{n-1} |U_i|\in[1,2*10^5]n[1,105],i=1n?1?Ui?[1,2?105]


解題思路

冬令營上講的題目,現在來寫。(而且好像我記得課上講的做法是bitsetbitsetbitset的,還是時間久了我記岔了?)

第一眼看上去直覺像是hallhallhall定理但還是不會。

hall定理:2?n2*n2?n個點的二分圖匹配,如果滿足任意kkk個點都連接了不少于kkk個點的話,那么這張圖就有完全匹配。

先套一下試試,發現滿足條件的圖對于它的每個子圖SSS滿足該子圖是一個森林。

換句話說對于任意一個UUU的集合TTTG(T)G(T)G(T)表示選出的邊連接的節點個數,那么一定有G(T)≥∣T∣+1G(T)\geq |T|+1G(T)T+1

回顧一下hallhallhall定理發現是不是很像。

可以先給每個點集選出一個各不同的點(也就是跑一次匹配),如果選不出來那么顯然無解。

然后考慮另一個點的選擇,從沒有被選擇的那個點入手,這個點可以選擇任何一個包含它的點集連接出去,然后就從下一個點集開始,直到回溯回來選擇下一個。如果最后能夠遍歷所有點就是合法的。

考慮一下正確性,如果它不能遍歷所有點那么沒有被遍歷的點集TTT無論怎么連接外面,就一定有一個環不滿足G(T)≥∣T∣+1G(T)\geq |T|+1G(T)T+1。如果它能遍歷所有點,那么我們已經構造出一個方案,顯然合法。

時間復雜度O(∑i=1n?1∣E∣n+n)O(\sum_{i=1}^{n-1}|E|\sqrt n+n)O(i=1n?1?En?+n)


code

#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=4e5+10,inf=1e9; struct node{int to,next,w; }a[N*2]; int n,s,t,tot=1,cnt,ans; int ls[N],p[N],b[N],dep[N],cur[N]; queue<int> q;bool v[N]; void addl(int x,int y,int w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;return; } bool bfs(){for(int i=1;i<=t;i++)cur[i]=ls[i],dep[i]=0;while(!q.empty())q.pop();q.push(s);dep[s]=1;while(!q.empty()){int x=q.front();q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dep[y]||!a[i].w)continue;dep[y]=dep[x]+1;if(y==t)return 1;q.push(y);}}return 0; } int dinic(int x,int flow){if(x==t)return flow;int rest=0,k;for(int &i=cur[x];i;i=a[i].next){int y=a[i].to;if(dep[x]+1!=dep[y]||!a[i].w)continue;rest+=(k=dinic(y,min(a[i].w,flow-rest)));a[i].w-=k;a[i^1].w+=k;if(rest==flow)return rest;}if(!rest)dep[x]=0;return rest; } void dfs(int x){cnt++;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(v[y])continue;b[y]=x;v[y]=1;dfs(p[y]);} } int main() {scanf("%d",&n);s=2*n;t=s+1;for(int i=1;i<n;i++){int m;scanf("%d",&m);for(int j=1;j<=m;j++){int x;scanf("%d",&x);addl(x,i+n,1);}}for(int i=1;i<=n;i++)addl(s,i,1);for(int i=1;i<n;i++)addl(i+n,t,1);while(bfs())ans+=dinic(s,inf);if(ans<n-1)return puts("-1")&0;for(int x=n+1;x<s;x++)for(int i=ls[x];i;i=a[i].next)if(a[i].w){p[x]=a[i].to;break;}v[s]=1;for(int i=ls[s];i;i=a[i].next)if(a[i].w)dfs(a[i].to);if(cnt<n)return puts("-1")&0;for(int x=n+1;x<s;x++)printf("%d %d\n",p[x],b[x]);return 0; }

總結

以上是生活随笔為你收集整理的AT4505-[AGC029F]Construction of a tree【构造题,hall定理,网络流】的全部內容,希望文章能夠幫你解決所遇到的問題。

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