zoukankan      html  css  js  c++  java
  • POJ 2396 Budget 有上下界的网络流

                                                                 POJ 2396  Budget

    题意简述:给定矩阵(每个元素都是非负整数)各行各列的和,并且限制其中的某些元素,给出一个可行解,特殊评测。矩阵规模小于200*20。

    网络流的模型是显而易见的,不过对于这道题,我们要添加两次源和汇。

    第一次添加s连接每一行,t连接每一列,容量上下线都是这行或这列的和。

    第二次对每条有容量限制的边(u,v)添加 (ss,v)和( u,tt)容量均为( u,v)的下限。

    第三次添加(t,s)容量无穷。

    对(ss,tt)求最大流,若ss出发和进入tt的边均满流则有解,并且可以直接输出解。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxm=200+50,INF=1e+8;
    int k,ans[maxm][maxm],cap[maxm][maxm],flow[maxm][maxm],low[maxm][maxm],up[maxm][maxm],n,m;
     vector<int> next[maxm];
    
    int d[maxm],fa[maxm],cur[maxm];
    bool vis[maxm];
    bool bfs(int s,int t)
    {
     memset(vis,0,sizeof(vis));
     memset(d,0,sizeof(d));
     queue<int>q;
     vis[s]=true;q.push(s);
     while(!q.empty())
     	{
     	 int np=q.front();q.pop();
     	 for(int i=0;i<next[np].size();i++)
     	 	{
     	 	 int ne=next[np][i];
     	 	 if(cap[np][ne]<=flow[np][ne]||vis[ne])continue;
     	 	 q.push(ne);
     	 	 vis[ne]=true;
     	 	 d[ne]=d[np]+1;
    		}
    	}
     return vis[t];
    }
    
    int dfs(int now,int t,int flo)
    {
     if(now==t||flo==0)return flo;
     int floww=0;
     for(int i=cur[now];i<next[now].size();i++)
     	{
     	 int np=next[now][i];
    	 if(d[np]!=d[now]+1)continue;
    	 if(cap[now][np]<=flow[now][np])continue;
    	 int fn=dfs(np,t,min(flo,cap[now][np]-flow[now][np]));
    	 flow[now][np]+=fn;
    	 flow[np][now]-=fn;
    	 floww+=fn;
    	 flo-=fn;
    	 if(flo==0)break; 
    	 cur[now]++;
    	}
     return floww;
    }
    int dinic(int s,int t)
    {
     int ans=0;
     while(bfs(s,t))
     	{
     	 memset(cur,0,sizeof(cur));
     	 ans+=dfs(s,t,INF);
    	}
     return ans;
    }
    void find(int s,int t)
    {
     memset(d,0,sizeof(d));
     d[s]=INF;
     queue<int>q;
     q.push(s);
     while(!q.empty())
     	{
     	 int u=q.front();
     	 q.pop();
     	 for(int i=0;i<next[u].size();i++)
     	 	{
     	 	 int nextp=next[u][i];
     	 	 if(d[nextp]!=0||(cap[u][nextp]-flow[u][nextp])<=0)continue;
     	 	 d[nextp]=min(d[u],(cap[u][nextp]-flow[u][nextp]));
     	 	 q.push(nextp);
     	 	 fa[nextp]=u;
     	 	 if(nextp==t)
     	 	 	{
     	 	 	 while(!q.empty())q.pop();
     	 	 	 return ;
    			}
    		}
    	}
    }
    int E_K(int s,int t)
    {
     int ans=0;
     memset(fa,0,sizeof(fa));
     while(true)
     	{
     	 find(s,t);
     	 ans+=d[t];
     	 if(d[t]==0)break;
     	 for(int i=t;i!=s;i=fa[i])
     	 	{
     	 	 flow[fa[i]][i]+=d[t];
     	 	 flow[i][fa[i]]-=d[t];
    		}
    	}
     return ans;
    }
    
    void addedge(int a,int b,vector<int> next[])
    {
     next[a].push_back(b);
     next[b].push_back(a);
     return ;
    }
    int main()
    {
     int N;
     int s=249,t=s-1,ss=t-1,tt=ss-1;
     scanf("%d",&N);
     for(int ii=1;ii<=N;ii++)
    {
        
         for(int i=0;i<maxm;i++)
         	while(next[i].size()>0)next[i].pop_back();
     	 memset(cap,0,sizeof(cap));memset(flow,0,sizeof(flow));
     	 memset(low,0,sizeof(low));memset(up,0,sizeof(up));
     	 scanf("%d%d",&m,&n);
     	 for(int i=1;i<=m;i++)
     	 	{
     	 	 int a;scanf("%d",&a);
     	 	 cap[s][i]=0;cap[ss][i]+=a;cap[s][tt]+=a;
     	 	 addedge(s,i,next);addedge(ss,i,next);addedge(i,tt,next);
     	 	 for(int j=201;j<=200+n;j++)
     	 	 	{
     	 	 	 addedge(i,j,next);
     	 	 	 up[i][j]=a;
    			}
     	 	}
    		addedge(s,tt,next);
    	 for(int i=201;i<=200+n;i++)
    	 	{
    	 	 int a;scanf("%d",&a);
    	 	 cap[i][t]=0;cap[ss][t]+=a;cap[i][tt]+=a;
    	 	 addedge(i,t,next);addedge(i,tt,next);addedge(i,ss,next);
    	 	 for(int j=1;j<=m;j++)
    	 	 	up[j][i]=min(up[j][i],a);
    		}
    		addedge(ss,t,next);
     int k;
     scanf("%d",&k);
     for(int iii=0;iii<k;iii++)
     	{
     	 int a,b,c;char t;
     	 scanf("%d%d",&a,&b);t=getchar();t=getchar();scanf("%d",&c);
     	 int ia,ib,ja,jb;
     	 if(a==0){ia=1;ib=m;}
     	 	else {ia=ib=a;}
     	 if(b==0){ja=201;jb=200+n;}
     	 	else{ja=jb=(200+b);}
     	 for(int i=ia;i<=ib;i++)
     	 	for(int j=ja;j<=jb;j++)
     	 		{
     	 		 if(t=='=')
     	 		 	{
     	 		 	 up[i][j]=min(up[i][j],c);low[i][j]=max(low[i][j],c);
    				}
    			 if(t=='>')
    			 	{
    			 	 low[i][j]=max(low[i][j],c+1);
    				}
    			 if(t=='<')
    			 	{
    			 	 up[i][j]=min(up[i][j],c-1);
    				}
    			}
    	}
     for(int i=1;i<=m;i++)
    	 	for(int j=201;j<=200+n;j++)
    	 		{
    	 		 cap[i][j]=up[i][j]-low[i][j];
    	 		 cap[ss][j]+=low[i][j];
    	 		 cap[i][tt]+=low[i][j];
    			}
     next[t].push_back(s);cap[t][s]=INF;
     dinic(ss,tt);
     bool impo=false;
     for(int i=1;i<=m;i++)
     	{
     	 if(flow[ss][i]!=cap[ss][i]){impo=true;break;}
     	 if(flow[i][tt]!=cap[i][tt]){impo=true;break;}
    	}
     for(int j=201;j<=200+n;j++)
     	{
     	 if(flow[ss][j]!=cap[ss][j]){impo=true;break;}
     	 if(flow[j][tt]!=cap[j][tt]){impo=true;break;}
    	}
     	 if(flow[s][tt]!=cap[s][tt]){impo=true;}
     	 if(flow[ss][t]!=cap[ss][t]){impo=true;}
     if(impo){printf("IMPOSSIBLE
    
    ");continue;}
     for(int i=1;i<=m;i++)
      {
     
     	for(int j=201;j<n+200;j++)
     		{
     		 printf("%d ",flow[i][j]+low[i][j]);
    		}
    	 printf("%d
    ",flow[i][200+n]+low[i][200+n]);
    	}
     printf("
    ");
    }
     return 0;
    }
    

      

                                        

  • 相关阅读:
    微信小程序学习心得
    微信小程序分类的实现
    Vue实例中封装api接口的思路 在页面中用async,await调用方法请求
    Vue中封装axios组件实例
    使用creata-react-app脚手架创建react项目时非常慢的问题
    Javascript的对象
    vue中上拉加载数据的实现
    Vue中键盘事件
    vant学习网址
    字符串,字典,数组写入本地文件和从本地文件读取
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6439685.html
Copyright © 2011-2022 走看看