http://acm.hdu.edu.cn/showproblem.php?pid=3277
#include<iostream>
using namespace std;
#define N 800
#define M 1000000
#define inf 0x7fffffff
struct Graph{
struct node{
int v,next,flow;
node(){};
node(int a,int b,int c):next(a),v(b),flow(c){};
}E[M],EE[M];
int pre[N];
int head[N];
int cur[N];
int dis[N];
int NV,NE;
int gap[N];
void init(int n){
memset(head,-1,sizeof(head));
NE=0;
NV=n;
}
void insert(int u,int v,int w){
E[NE]=node(head[u],v,w);
head[u]=NE++;
E[NE]=node(head[v],u,0);
head[v]=NE++;
}
int SAP(int s,int t){
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
for(int i=0;i<NV;i++)
cur[i]=head[i];
int u=pre[s]=s;
int maxflow=0,aug=inf;
gap[0]=NV;
while(dis[s]<NV){
loop: for(int &i=cur[u];i!=-1;i=E[i].next){
int v=E[i].v;
if(E[i].flow&&dis[u]==dis[v]+1){
if(aug>E[i].flow)
aug=E[i].flow;
pre[v]=u;
u=v;
if(v==t){
maxflow+=aug;
for(u=pre[u];v!=s;v=u,u=pre[u]){
E[cur[u]].flow-=aug;
E[cur[u]^1].flow+=aug;
}
aug=inf;
}
goto loop;
}
}
int mindis=NV;
for(int i=head[u];i!=-1;i=E[i].next){
int v=E[i].v;
if(E[i].flow&&mindis>dis[v]){
cur[u]=i;
mindis=dis[v];
}
}
if(--gap[dis[u]]==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}
}G;
int bin[300];
int find(int x){
if(bin[x]==x)
return bin[x];
return bin[x]=find(bin[x]);
}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
bin[fx]=fy;
}
struct NN{
int a,b;
}p[70000];
bool h[300][300];
int main(void){
int t;
scanf("%d",&t);
while(t--){
int n,m,k,f,l;
scanf("%d%d%d%d",&n,&m,&k,&f);
for(int i=0;i<m;i++)
scanf("%d%d",&p[i].a,&p[i].b);
int beg=3*n+1,end=beg+1;
for(int i=0;i<=n;i++)
bin[i]=i;
while(f--){
int u,v;
scanf("%d%d",&u,&v);
merge(u,v);
}
for(int i=1;i<=n;i++)
find(i);
G.init(end);
for(int i=1;i<=n;i++){
G.insert(beg,i,0);
G.insert(i+2*n,end,0);
}
for(int i=1;i<=n;i++)
G.insert(i,i+n,k);
memset(h,0,sizeof(h));
for(int i=0;i<m;i++){
int a=p[i].a,v=p[i].b;
for(int u=1;u<=n;u++){
if(bin[u]==bin[a]&&!h[u][v]){
h[u][v]=1;
G.insert(u,v+2*n,1);
}
}
}
for(int u=1;u<=n;u++)
for(int v=1;v<=n;v++)
if(!h[u][v])
G.insert(u+n,v+2*n,1);
for(int i=0;i<G.NE;i++)
G.EE[i]=G.E[i];
f=0;l=n;
int ret;
while(f<=l){
int mid=(f+l)>>1;
for(int i=0;i<G.NE;i++)
G.E[i]=G.EE[i];
for(int i=0;i<4*n;i++)
G.E[i].flow=mid;
if(G.SAP(beg,end)==n*mid){
f=mid+1;
ret=mid;
}
else
l=mid-1;
}
printf("%d\n",ret);
}
}
可以把初始建的边先保存一下,二分的时候只要改变源点与汇点的边容量就行,这样速度可以加快很多,为了方便,我是先建这两种边的,所以只需要改变0到4*n的边容量就行