LightOJ

来源:互联网 发布:仓管软件 免费 编辑:程序博客网 时间:2024/05/20 18:02

原题地址:点击打开链接

由于该题顶点上有流量的限制,所以我们要先进行拆点,比如u点的流量限制为p的话,建边 u->u+n流量为p,在建立超级源点s,与汇点t,则该题转化为

普通的最大流问题,该题用Ford-Fulkerson算法的话会超时,所以我们用Dinic算法进行求解。

#include<stdio.h>#include<string.h>#include<vector>#include<queue>#define INF 1<<31-1#define min(x,y)(x<y?x:y)using namespace std;struct Edge{int to;int cap;int rev;};int p[110];int used[210];int len[210];int pos[210];vector<Edge>g[210];void add_edge(int from,int to,int cap){g[from].push_back((Edge){to,cap,g[to].size()});g[to].push_back((Edge){from,0,g[from].size()-1});}    bool bfs(int s,int t)                        //分层       {          int i;          memset(len,-1,sizeof(len));          queue<int>que;          que.push(s);          len[s]=0;          while(!que.empty())          {              int u=que.front();              que.pop();              for(i=0;i<g[u].size();i++)              {              Edge e=g[u][i];            int v=e.to;                if(e.cap>0 && len[v]<0)                  {                      len[v]=len[u]+1;                      que.push(v);                  }              }          }          if(len[t]>-1)              return true;          return false;      }      int dfs(int u,int t,int f)       //寻找增广路       {          if(u==t)              return f;          for(int &i=pos[u];i<g[u].size();i++)    //注意该处的引用,意思就是从上次遍历过的地方开始           {          Edge &e=g[u][i];            int v=e.to;            if(e.cap>0 && len[u]==len[v]-1)              {                  int d=dfs(v,t,min(e.cap,f));                  if(d>0)                  {                      e.cap-=d;                      g[v][e.rev].cap+=d;                      return d;                  }              }          }          return 0;      }      int max_flow(int s,int t)      {          int res=0;                    while(bfs(s,t))                      {              memset(pos,0,sizeof(pos));              while(1)              {                  int d=dfs(s,t,INF);                  if(d<=0)                      break;                  res+=d;              }          }          return res;      }  int main(){int i,c,n,m,b,d,from,to,cap,k=0,s,t;scanf("%d",&c);while(c--){scanf("%d",&n);s=0;                   //源点 t=n*2+1;                //汇点for(i=0;i<=t;i++)g[i].clear(); for(i=1;i<=n;i++){scanf("%d",&p[i]);add_edge(i,i+n,p[i]);}scanf("%d",&m);for(i=0;i<m;i++)                  //建图 {scanf("%d%d%d",&from,&to,&cap);add_edge(from+n,to,cap);}scanf("%d%d",&b,&d);for(i=0;i<b;i++){scanf("%d",&to);add_edge(s,to,INF);}for(i=0;i<d;i++){scanf("%d",&from);add_edge(from+n,t,INF);}int res=max_flow(s,t);printf("Case %d: %d\n",++k,res);}return 0;}


0 0
原创粉丝点击