HDU 3277 Marriage Match III

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的边容量就行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值