poj 1459 (一不小心就超时的网络流 + Dinic)

来源:互联网 发布:杭州网络维护外包 编辑:程序博客网 时间:2024/04/27 17:41
题目大意:总共有n个节点,其中有发电站np个、用户nc个和调度器n-np-nc个三种节点,每个发电站有一个最大发电量,每个用户有个最大接受电量,现在有m条有向边,边有一个最大的流量代表,最多可以流出这么多电,现在从发电站发电到用户,问最多可以发多少电

解题思路:将发电站看成源点,用户看成汇点,这样求最大流就可以了,不过因为有多个源点和汇点,所以加一个超级源点指向所有的发电站,流量为无限大,加一个超级汇点让所有的用户指向他,流量也为无限大,这样,从超级源点到超级汇点求最大流即可


sap:(会超时)


#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=200;const int M=50000;const int inf=1<<30 ;struct node{int u ,v,c,next;}edge[M];int head[N],dis[N],gap[N],cur[N],pre[N];int top ;void add(int u ,int v,int c){edge[top].u=u;edge[top].v=v;edge[top].c=c;edge[top].next=head[u];head[u]=top++;edge[top].u=v;edge[top].v=u;edge[top].c=0;edge[top].next=head[v];head[v]=top++;}int sap(int s,int t,int nv){memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i = 1 ; i <= nv ; i++)  cur[i]=head[i];int u,v,flow=0,min_flow=inf ;pre[s]=u=s;gap[s]=nv;while(dis[s] < nv){  loop :   for(int &j=cur[u];j!=-1 ;j=edge[j].next)   {      v=edge[j].v;      if( edge[j].c >0 && dis[u]==dis[v]+1)      {             pre[v]=u;             u=v;             min_flow = min( min_flow ,edge[j].c);             if(v==t)             {                 for(u=pre[v];v!=s;v=u,u=pre[u])    {      edge[cur[u]].c -= min_flow;      edge[cur[u]^1].c += min_flow ;   }                  flow += min_flow ;                  min_flow = inf ;             }           goto loop ;      }   }   int mindis=nv;   for(int i = head[u] ; i!=-1 ; i=edge[i].next)   {        v=edge[i].v;        if(edge[i].c > 0 && dis[v] < mindis )        {            cur[u]=i;            mindis=dis[v];         }   }    if(--gap[dis[u]]==0) break ;   gap[dis[u]=mindis+1]++;   u=pre[u]; }return flow ;}int main(){int n,np,nc,m,u,v,w;char ch ;while(~scanf("%d%d%d%d",&n,&np,&nc,&m)){    top=0;memset(head,-1,sizeof(head));int s=0,t=n+1;for(int i = 1 ; i <= m ; i++){cin>>ch>>u>>ch>>v>>ch>>w ;add(u+1,v+1,w);}for(int i = 1 ; i <= np ; i++){   cin>>ch>>u>>ch>>w;   add(s,u+1,w);}for(int i = 1 ; i<= nc ; i++){cin>>ch>>u>>ch>>w;add(u+1,t,w);} int ans=Isap(s,t,t+1); printf("%d\n",ans);}return 0;} 


Dinic:(AC)

#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=200;const int M=50000;const int inf=1<<30 ;struct node{int u ,v,c,next;}edge[M];int head[N],dis[N],gap[N],cur[N],pre[N];int top ,s,t;void add(int u ,int v,int c){edge[top].u=u;edge[top].v=v;edge[top].c=c;edge[top].next=head[u];head[u]=top++;edge[top].u=v;edge[top].v=u;edge[top].c=0;edge[top].next=head[v];head[v]=top++;}int BFS(){    memset(dis,-1,sizeof(dis));queue<int>q ;q.push(s);     dis[s]=0;    while(!q.empty())    {      int u = q.front();      q.pop();      for(int i = head[u] ; i!=-1 ; i=edge[i].next)      {         int v =edge[i].v ;         if(edge[i].c >0 && dis[v]==-1)         {               dis[v]=dis[u]+1;               q.push(v);         }            }    }    if(dis[t]==-1)      return 0;    return 1;  } int DFS(int u ,int minx){if(u==t)  return minx ;int tmp ;for(int i = head[u];i!=-1 ; i=edge[i].next){      int v=edge[i].v;if(edge[i].c >0 && dis[v]==dis[u]+1 && (tmp=DFS(v,min(minx,edge[i].c)))){    edge[i].c -= tmp;    edge[i^1].c+=tmp;    return tmp ;     }}         //一般的Dinic没有这句dis[u]=-1;有时不加也能AC; dis[u]=-1; //不加这句 会超时,表示以u点往下的都搜完了,如今回溯完以后,今后就不在访问u点。 return 0;}int Dinic(){int ans= 0 , tmp;while(BFS())    //找层次图 ,直到不能找到 {  while(1)  {       tmp = DFS(s,inf);  //找增广路    if(tmp==0) break; ans += tmp ;        }}return ans ;}int main(){int n,np,nc,m,u,v,w;char ch ;while(~scanf("%d%d%d%d",&n,&np,&nc,&m)){    top=0;memset(head,-1,sizeof(head)); s=0,t=n+1;for(int i = 1 ; i <= m ; i++){cin>>ch>>u>>ch>>v>>ch>>w ;add(u+1,v+1,w);}for(int i = 1 ; i <= np ; i++){   cin>>ch>>u>>ch>>w;   add(s,u+1,w);}for(int i = 1 ; i<= nc ; i++){cin>>ch>>u>>ch>>w;add(u+1,t,w);} int ans=Dinic(); printf("%d\n",ans);}return 0;} 



                                             
0 0
原创粉丝点击