HDU 3081 並查集+二分+最大流
阿新 • • 發佈:2018-12-31
AC程式碼
#include<bits/stdc++.h> using namespace std; #define maxn 500 #define maxm 10000000 #define inf 0x3f3f3f3f int first[maxn]; int edge_num; int lev[maxn]; int vis[maxn]; int father[maxn]; int n,m,f; vector<int>vec1[maxn]; set<int>vec2[maxn]; set<int>vec3[maxn]; struct edge{ int u,v; int cap; int next; }e[maxm]; int find(int x) { return father[x]==x?x:father[x]=find(father[x]); } void merge(int a,int b) { a=find(a); b=find(b); if(a!=b) father[a]=b; } void init() { edge_num=0; memset(first,-1,sizeof(first)); } void add_edge(int u,int v,int c) { e[edge_num].u=u; e[edge_num].v=v; e[edge_num].cap=c; e[edge_num].next=first[u]; first[u]=edge_num++; e[edge_num].u=v; e[edge_num].v=u; e[edge_num].cap=0; e[edge_num].next=first[v]; first[v]=edge_num++; } int Dinic_spath(int s,int t) { queue<int>q; q.push(s); memset(lev,-1,sizeof(lev)); memset(vis,0,sizeof(vis)); lev[s]=0; while(!q.empty()) { int u=q.front(); vis[u]=0; q.pop(); for(int k=first[u];k!=-1;k=e[k].next) { int v=e[k].v; if(lev[v]==-1&&e[k].cap>0) { lev[v]=lev[u]+1; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return lev[t]!=-1; } int Dinic_dfs(int u,int t,int flow) { int cost=0; if(u==t) return flow; for(int k=first[u];k!=-1;k=e[k].next) { int v=e[k].v; if(lev[v]==lev[u]+1&&e[k].cap>0) { int minn=Dinic_dfs(v,t,min(e[k].cap,flow-cost)); if(minn>0) { e[k].cap=e[k].cap-minn; e[k^1].cap=e[k^1].cap+minn; cost+=minn; if(cost==flow) break; } else lev[v]=-1; } } return cost; } bool judge(int x) { init(); for(int i=1;i<=n;++i) add_edge(0,i,x); for(int i=1;i<=n;++i) { for(auto j=vec2[i].begin();j!=vec2[i].end();++j) { int v=*j; add_edge(i,n+v,1); } } for(int i=n+1;i<=2*n;++i) add_edge(i,2*n+1,x); int ans=0; while(Dinic_spath(0,2*n+1)) ans+=Dinic_dfs(0,2*n+1,inf); return ans>=x*n; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&f); for(int i=0;i<=n;++i) { vec1[i].clear(); vec2[i].clear(); vec3[i].clear(); father[i]=i; } for(int i=1;i<=m;++i) { int a,b; scanf("%d%d",&a,&b); vec1[a].push_back(b); } for(int i=1;i<=f;++i) { int a,b; scanf("%d%d",&a,&b); merge(a,b); } for(int i=1;i<=n;++i) vec3[find(i)].insert(vec1[i].begin(),vec1[i].end()); for(int i=1;i<=n;++i) vec2[i]=vec3[find(i)]; int l=0,r=n; int ans=0; while(l<=r) { int mid=(l+r)>>1; if(judge(mid)) { ans=mid; l=mid+1; } else r=mid-1; } printf("%d\n",ans); } }