• P3254 圆桌问题


    Aimee

    看起来就是个匹配问题

    建模 超级源点和汇点是必须的,那么这样看来,我们把每个单位和每张桌子连一张容量为1的边,表示只能派一个人,超级源点和每个单位连对应人数的边,桌子同理,然后跑最大流并且检查最大流和人数就可以

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int n,m,s,t;
    int p=1;
    int x,y,z;
    int head[605];
    long long Aimee;
    queue<int> q;
    struct e{
    	int to;
    	long long v;
    	int ne;
    }ed[200001];
    void add(int f,int t,int v){
    	ed[++p].ne=head[f];ed[p].to=t;ed[p].v=v;head[f]=p;
    	ed[++p].ne=head[t];ed[p].to=f;ed[p].v=0;head[t]=p;
    }
    int vis[100001];
    long long exf[100001];
    int pre[10001];
    int le[10001];
    int fr[10001];
    const long long inf=(1<<29);
    bool bfs(){
    	memset(le,-1,sizeof(le));
    	while(!q.empty()){
    		q.pop();
    	}
    	q.push(s);
    	le[s]=0;
    	fr[s]=head[s];
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=head[u];i;i=ed[i].ne){
    			int v=ed[i].to;
    			if(ed[i].v&&le[v]==-1){
    				q.push(v);le[v]=le[u]+1;
    				fr[v]=head[v];
    				if(v==t) return 1;
    			}
    		}
    	}
    	return 0;
    } 
    long long dfs(int now,int tas){
    	if(now==t) return tas;
    	long long znx=0;
    	for(int i=fr[now];i&&znx<tas;i=ed[i].ne){
    		fr[now]=i;
    		int v=ed[i].to;
    		if(ed[i].v&&le[v]==le[now]+1){
    			long long jdn=dfs(v,min(tas-znx,ed[i].v));
    			if(!jdn) le[v]=-1;
    			ed[i].v-=jdn;
    			ed[i^1].v+=jdn;
    			znx+=jdn;
    		}
    	}
    	return znx;
    }
    long long znx;
    long long dinic(){
    	while(bfs()){
    		while(znx=dfs(s,inf)){
    			Aimee+=znx;
    		}
    	}
    	return Aimee;
    }
    int sum;
    int main(){
    	scanf("%d%d",&m,&n);
    	s=n+m+2;
    	t=n+m+1;
    	for(int i=1;i<=m;++i){
    		scanf("%d",&x);
    		add(s,i,x);
    		sum+=x;
    	}	
    	for(int i=1;i<=n;++i){
    		scanf("%d",&x);
    		add(i+m,t,x);
    	}
    	for(int i=1;i<=m;++i){
    		for(int j=1;j<=n;++j){
    			add(i,j+m,1);
    		}
    	}
    	int Archie=dinic();
    	if(sum!=Archie){
    		cout<<0;
    		return 0;
    	}
    	cout<<1<<endl;
    	for(int i=1;i<=m;++i){
    		for(int j=head[i];j;j=ed[j].ne){
     			if(ed[j].to!=s&&ed[j].v==0){
    			 cout<<ed[j].to-m<<" "; 
    			 } 
    		}
    		cout<<endl;
    	}
    	return 0;
    } 
    
  • 相关阅读:
    php-管理变量
    php-变量的间接引用
    php-eval()
    HTML
    php观
    笔记1
    脚本语言
    Windows Server 2012如何把快捷方式加到启动文件夹中
    VIM的笔记
    mongodb 从3.0 升级到3.2
  • 原文地址:https://www.cnblogs.com/For-Miku/p/14748684.html
Copyright © 2020-2023  润新知