Power Network POJ - 1459 网络流 DInic 模板

  1 #include<cstring>
  2 #include<cstdio>
  3 #define FOR(i,f_start,f_end) for(int i=f_startl;i<=f_end;i++)
  4 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
  5 const int maxn=500;
  6 const int maxm=2e4+5;
  7 int size;
  8 int n;
  9 const int inf=0x3f3f3f3f;
 10 using namespace std;
 11 int head[maxn];
 12 void init(){
 13     size=0;
 14     MS(head,-1);
 15 }
 16 struct Node{
 17     int from,to,cap,next;
 18 }edge[maxn];
 19 void add(int u,int v,int w){
 20     edge[size].from=u;
 21     edge[size].to=v;
 22     edge[size].cap=w;
 23     edge[size].next=head[u];
 24     head[u]=size++;
 25     edge[size].from=v;
 26     edge[size].to=u;
 27     edge[size].cap=w;
 28     edge[size].next=head[v];
 29     head[v]=size++;
 30 }
 31 int dep[maxn];
 32 int bfs(int start,int end){
 33     int que[maxn];
 34     int front,rear;
 35     MS(dep,-1);
 36     que[rear++]=start;
 37     dep[start]=0;
 38     while(front!=rear){
 39         int u=que[front++];
 40         if(front==maxn)front=0;
 41         for(int i=head[u];i!=-1;i=edge[i].next){
 42             int v=edge[i].to;
 43             if(edge[i].cap>0&&dep[v]==-1){
 44                 dep[v]=dep[u]+1;
 45                 que[rear++]=v;
 46                 if(rear>=maxn)rear=0;
 47                 if(v==end)return 1;//优化1 找到直接返回
 48             }
 49         }
 50     }
 51     return 0;
 52 
 53 }
 54 int dinic(int start,int end){
 55 
 56     int res=0;
 57     int top;
 58     int stack[maxn];//非递归 手写栈
 59     int cur[maxn];
 60     while(bfs(start,end)){
 61         memcpy(cur,head,sizeof(head));//当前弧预备工作
 62         int u=start;
 63         top=0;
 64         while(1){
 65             if(u==end){//当找到终点的时候
 66             int min=inf;
 67             int loc;
 68             for(int i=0;i<top;i++){//找到路径里面最小的流量
 69                 if(min>edge[stack[i]].cap){
 70                     min=edge[stack[i]].cap;
 71                     loc=i;//记下最小流量的边 之后的点都不可能到达了
 72                 }
 73             }
 74             for(int i=0;i<top;i++){//减流量和加反向边
 75                 edge[stack[i]].cap-=min;
 76                 edge[stack[i]^1].cap+=min;
 77             }
 78             res+=min;
 79             top=loc;//退栈顶到那个流量已经清零的边的起点i
 80             u=edge[stack[top]].from;
 81         
 82               }
 83             for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)//当前弧优化如果存在以下情况的时候就可以break进行操作了
 84                 if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
 85                     break;
 86             if(cur[u]!=-1){//如果有边可以走 那么就把边和点入栈
 87                 stack[top++]=cur[u];
 88                 u=edge[cur[u]].to;
 89             }
 90             else {//如果从栈顶点出发找不到可以增广的路径了,那么如果栈已经空了 那可能就没有可以增广的路径了,而如果栈没有空 那么就退栈继续找
 91                 if(top==0)break;
 92                 dep[u]=-1;//因为从u已经找不到可以走的路径了 直接把dep[u]=-1相当于没有点可以可以通过dep[u]+1==dep[edge[i].to]的条件 也就是u以后也入不了栈了
 93                 u=edge[stack[--top]].from;
 94             }
 95         }
 96     }
 97     return res;
 98 }
 99 int main(){
100     int start,end;
101     int np,nc,m;
102     int u,v,z;
103     while(scanf("%d%d%d%d",&n,&np,&nc,&m)==4){
104         init();
105     while(m--){
106         while(getchar()!='(');
107         scanf("%d,%d)%d",&u,&v,&z);
108         u++,v++;
109         add(u,v,z);
110         
111     }
112     while(np--){
113         while(getchar()!='(');
114         scanf("%d)%d",&u,&z);
115         u++;
116         add(0,u,z);
117     }
118     while(nc--){
119         while(getchar()!='(');
120         scanf("%d)%d",&u,&v);
121         u++;
122         add(u,n+1,z);
123     }
124     start=0;
125     end=n+1;
126     int ans=dinic(start,end);
127     printf("%d\n",ans);
128     }
129 return 0;
130 }

猜你喜欢

转载自www.cnblogs.com/ttttttttrx/p/10548211.html