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;
    }
    

      

                                        

  • 相关阅读:
    oracle 10g 免安装客户端在windows下配置
    sql2005 sa密码
    使用windows live writer 有感
    windows xp SNMP安装包提取
    汉化groove2007
    迁移SQL server 2005 Reporting Services到SQL server 2008 Reporting Services全程截图操作指南
    foxmail 6在使用中的问题
    AGPM客户端连接不上服务器解决一例
    SpringSource Tool Suite add CloudFoundry service
    Java 之 SWing
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6439685.html
Copyright © 2011-2022 走看看