Address: HDU 3277
This is similar to the method of creating a graph in the previous version of this question, but it only needs to be split. This split point is also clever. It not only limits the traffic, but also only a part of it. I used to think that the split point would have all the restrictions. It can also be used to separate the restrictions and learn.
The method for creating a graph is to create a source and sink, split the girl into I and I + N, and link the I to the Source Vertex. The weight is mid, edge connecting I and I + n. The weight is k, and then the edge connecting the boy and the sink is mid, in this case, I can be paired with the corresponding boy. The weight is 1. If I + N cannot be paired with the corresponding boy, in this way, no traffic limit is imposed on the original matching, and no matching limit is imposed on the traffic K. Finally, determine whether the stream is full.
This time, I got stuck in and checked the set .... =! It's speechless .. However, this time the card was stuck in optimization. This time the data volume was large and the last method was used to talk to TLE, so this time the last method was no longer used, this is to mark the child nodes that can be paired with each other, and then traverse them directly. The last tag is a pair tag for each set .. The application of the parallel query set is still not flexible ..
The Code is as follows:
#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <ctype.h>#include <queue>#include <map>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int head[800], source, sink, nv, cnt;int cur[800], d[800], num[800], pre[800], q[800], bin[800], _hash[300][300];struct N{ int boy, girl;}pari[1000000];int find1(int x){ return bin[x]==x?x:bin[x]=find1(bin[x]);}void merger(int x, int y){ int f1=find1(x); int f2=find1(y); if(f2!=f1) bin[f2]=f1;}struct node{ int u, v, cap, next;}edge[1000000];void add(int u, int v, int cap){ edge[cnt].v=v; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].cap=0; edge[cnt].next=head[v]; head[v]=cnt++;}void bfs(){ memset(d,-1,sizeof(d)); memset(num,0,sizeof(num)); queue<int>q; q.push(sink); d[sink]=0; num[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(d[v]==-1) { d[v]=d[u]+1; num[d[v]]++; q.push(v); } } }}int isap(){ memcpy(cur,head,sizeof(cur)); bfs(); int flow=0, u=pre[source]=source, i; while(d[source]<nv) { if(u==sink) { int f=INF, pos; for(i=source;i!=sink;i=edge[cur[i]].v) { if(f>edge[cur[i]].cap) { f=edge[cur[i]].cap; pos=i; } } for(i=source;i!=sink;i=edge[cur[i]].v) { edge[cur[i]].cap-=f; edge[cur[i]^1].cap+=f; } flow+=f; u=pos; } for(i=cur[u];i!=-1;i=edge[i].next) { if(d[edge[i].v]+1==d[u]&&edge[i].cap) { break; } } if(i!=-1) { cur[u]=i; pre[edge[i].v]=u; u=edge[i].v; } else { if(--num[d[u]]==0) break; int mind=nv; for(i=head[u];i!=-1;i=edge[i].next) { if(mind>d[edge[i].v]&&edge[i].cap) { mind=d[edge[i].v]; cur[u]=i; } } d[u]=mind+1; num[d[u]]++; u=pre[u]; } } return flow;}int main(){ int t, n, m, k, f, i, j, a, b; scanf("%d",&t); while(t--) { scanf("%d%d%d%d",&n,&m,&k,&f); for(i=1;i<=m;i++) { scanf("%d%d",&pari[i].girl,&pari[i].boy); } for(i=1;i<=n;i++) { bin[i]=i; } while(f--) { scanf("%d%d",&a,&b); merger(a,b); } int high=n, low=0, mid, ans, x; while(low<=high) { mid=(low+high)/2; source=0; sink=3*n+1; nv=sink+1; memset(head,-1,sizeof(head)); cnt=0; memset(_hash,0,sizeof(_hash)); for(i=1;i<=n;i++) { add(source,i,mid); add(i,i+n,k); add(2*n+i,sink,mid); } for(i=1;i<=m;i++) { int a=pari[i].girl; int b=pari[i].boy; _hash[find1(a)][b]=1; } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(_hash[find1(i)][j]) { add(i,j+2*n,1); } else { add(i+n,j+2*n,1); } } } x=isap(); if(x>=n*mid) { ans=mid; low=mid+1; } else { high=mid-1; } } printf("%d\n",ans); } return 0;}