网络流(最大流、最小费用最大流、有上下界的网络流)

最大流的算法:

Ford-Fulkerson算法 
求最大流的过程,就是不断找到一条源到汇 的路径,然后构建残余网络,再在残余网络 上寻找新的路径,使总流量增加,然后形成 新的残余网络,再寻找新路径…..直到某个 残余网络上找不到从源到汇的路径为止,最 大流就算出来了。  
每次寻找新流量并构造新残余网络的过程, 就叫做寻找流量的“增广路径”,也叫“增 广” 
现在假设每条边的容量都是整数   
这个算法每次都能将流至少增加1    
由于整个网络的流量最多不超过 图中所有的边的容 量和C,从而算法会结束  
现在来看复杂度 找增广路径的算法可以用dfs,  
复杂度为边数m+顶 点数n Dfs 最多运行C次 所以时间复杂度为C*(m+n) =C* n^
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+107;
const int inf=0x3f3f3f3f;
struct node{
    int to;//终点
    int cap;//容量
    int rev;//反向边
};
vector<node> v[N];
bool used[N];
void add(int from,int to,int cap)
{
    v[from].push_back((node) {to,cap ,v[to].size()    });
    v[to].push_back((node)   {from,0 ,v[from].size()-1});
}
int dfs(int s,int t,int f)
{
    if(s==t) return f;
    used[s]=true;
    for(int i=0;i<v[s].size();i++)
    {
        node &tmp=v[s][i];
        if(used[tmp.to]==false&&tmp.cap>0)
        {
            int d=dfs(tmp.to,t,min(f,tmp.cap));
            if(d>0)
            {
//                tmp.cap-=d;
                v[s][i].cap-=d;
                v[tmp.to][tmp.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s,int t)
{
    int flow=0;
    while(1)
    {
        memset(used,false,sizeof(used));
        int f=dfs(s,t,inf);
        if(f==0) return flow;
        flow+=f;
    }
}
int main()
{
    int n,m,i,j,k,t;
    while(~scanf("%d%d",&n,&m))
    {
        memset(v,0,sizeof(v));
        for(i=0;i<n;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
        }
        printf("%d\n",max_flow(1,m));
    }
    return 0;
}
Dinic 算法 
Edmonds-Karp的提高余地:需要多次从s到t调 用BFS,可以设法减少调用次数。 
亦即:使用一种代价较小的高效增广方法。 
考虑:在一次增广的过程中,寻找多条增广路 径。 
DFS 
Dinic算法的实现有以下几个步骤:
1:初始化容量网络和网络流
2:构造残留网络和层次网络,若汇点不在层次网络中则算法结束 输出最大流
3:在层次网络中用一次DFS进行增广,DFS执行完毕,该阶段的增广也就完毕了。
4:转至步骤2
#include<bits/stdc++.h>
using namespace std;
const int N=205;
const int M=100010;
const int inf=0x3f3f3f3f;
int n,m,si,ei,ci;
int level[N];
struct node{
    int c,f;
}mp[N][N];
bool dinic_bfs()
{
    queue<int> q;
    memset(level,0,sizeof level);
    q.push(1);
    level[1]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int v=1;v<=m;v++)
        if(!level[v]&&mp[u][v].c>mp[u][v].f)
        {
            level[v]=level[u]+1;
            q.push(v);
        }
    }
    return level[m]!=0;
}
int dinic_dfs(int u,int cp)
{
    int tmp=cp;
    if(u==m) return cp;
    for(int v=1;v<=m&&tmp;v++)
    if(level[u]+1==level[v])
    {
        if(mp[u][v].c>mp[u][v].f)
        {
            int t=dinic_dfs(v,min(tmp,mp[u][v].c-mp[u][v].f));
            mp[u][v].f+=t;
            mp[v][u].f-=t;
            tmp-=t;
        }
    }
    return cp-tmp;
}
int dinic()
{
    int sum=0,tf=0;
    while(dinic_bfs())
    {
        while(tf=dinic_dfs(1,inf))
        {
            sum+=tf;
        }
    }
    return sum;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(mp,0,sizeof mp);
        while(n--)
        {
            scanf("%d%d%d",&si,&ei,&ci);
            mp[si][ei].c+=ci;
        }
        printf("%d\n",dinic());
    }
    return 0;
最小费用最大流

1.求出从发点到收点的最小费用路u(s,t)
2.对该通路u(s,t)分配最大可能 的流量:f
  并让通路上所有边的容量相应减少f。这时,对于通路上的饱和边,其单位流费用相应改为 +无穷
3.作该通路u(s,t)上所有边(i,j)的反向边(j,i),令
4.在这样构成 的新网络中,重复上述步骤1,2,3,到从发点到收点全部流量等于f为止(或者再也找不到从S到T 的最小费用通路)。

反复用spfa算法做源到汇的最短路进行增广,边 权值为边上单位费用。反向边上的单位费用是负 的。  
直到无法增广,即为找到最小费用最大流。   
成立原因:每次增广时,每增加1个流量,所增 加的费用都是最小的。  
因为有负权边(取消流的时候产生的),所以不 能用迪杰斯特拉算法求最短路。 

http://poj.org/problem?id=2135
//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
using namespace std;
const int N=1050;
const int M=40050;
const int inf=0x3f3f3f3f;
struct node{
    int from,to,flow,cap,cost;
    node(){}
    node(int a,int b,int c,int d,int e)
    {
        from=a;to=b;flow=c;cap=d;cost=e;
    }

};
vector<int> g[N];
vector<node> mp;
void add(int a,int b,int c,int d)
{
    mp.push_back(node(a,b,0,c,d));
    mp.push_back(node(b,a,0,0,-d));
    int total=mp.size();
    g[a].push_back(total-2);
    g[b].push_back(total-1);
}
int dis[N],P[N],A[N];
bool used[N];
int m,n,flow,cost;
bool spfa(int s,int t)
{
    memset(dis,inf,sizeof dis);
    memset(used,0,sizeof used);
    dis[s]=0;used[s]=1;P[s]=0;A[s]=inf;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        used[u]=0;
        for(int i=0;i<g[u].size();i++)
        {
            node tmp=mp[g[u][i]];
            if(tmp.cap>tmp.flow&&dis[tmp.to]>dis[u]+tmp.cost)
            {
                dis[tmp.to]=dis[u]+tmp.cost;
                P[tmp.to]=g[u][i];
                A[tmp.to]=min(A[u],tmp.cap-tmp.flow);
                if(!used[tmp.to]) q.push(tmp.to),used[tmp.to]=1;
            }
        }
    }
    if(dis[t]==inf) return 0;
    flow+=A[t];
    cost+=dis[t]*A[t];
    int u=t;
    while(u!=s){
        mp[P[u]].flow+=A[t];
        mp[P[u]^1].flow-=A[t];
        u=mp[P[u]].from;
    }
    return 1;
}
int mincost(int s,int t)
{
    flow=cost=0;
    while(spfa(s,t));
    return cost;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(g,0,sizeof g);
        mp.clear();
        int s=0,t=n+1,u,v,c;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,1,c);
            add(v,u,1,c);
        }
        add(s,1,2,0);
        add(n,t,2,0);
        printf("%d\n",mincost(s,t));
    }
    return 0;
}

有上下界的网络流

1、无源汇有上下界最大流
解题思路:O(-1)。
 建图模型: 以前写的最大流默认的下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理。对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low。可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流”,我们增设一个超级源点st和一个超级终点sd。我们开设一个数组du[]来记录每个节点的流量情况。

du[i]=in[i](i节点所有入流下界之和)-out[i](i节点所有出流下界之和)。

当du[i]大于0的时候,st到i连一条流量为du[i]的边。

当du[i]小于0的时候,i到sd连一条流量为-du[i]的边。

最后对(st,sd)求一次最大流即可,当所有附加边全部满流时(即maxflow==所有du[]>0之和),有可行解。

 题目链接:  sgu194 Reactor Cooling
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;


const int maxn=1000+10;
const int INF=0x7FFFFFFF;

struct Edge
{
    int from,to,cap,flow,up,low;
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int Out[maxn],In[maxn];
int s,t;

//求出层次网络
bool BFS()
{
    memset(vis,0,sizeof(vis));
    queue<int>Q;
    Q.push(s);
    d[s]=0;
    vis[s]=1;
    while(!Q.empty())
    {
        int x=Q.front();
        Q.pop();
        for(int i=0; i<G[x].size(); i++)
        {
            Edge& e=edges[G[x][i]];
            if(!vis[e.to]&&e.cap>e.flow)
            {
                vis[e.to]=1;
                d[e.to]=d[x]+1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}


//加边
void AddEdge(int from,int to,int low,int up)
{
    int m;
    Edge r;
    r.from=from;
    r.to=to;
    r.cap=up-low;
    r.flow=0;
    r.low=low;
    r.up=up;
    edges.push_back(r);
    Edge d;
    d.from=to;
    d.to=from;
    d.cap=0;
    d.flow=0;
    //r.low=low;r.up=up;
    edges.push_back(d);
    m=edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}

//每个阶段来一次DFS增广
int DFS(int x,int a)
{
    if(x==t||a==0) return a;
    int flow=0,f;
    for(int i=cur[x]; i<G[x].size(); i++)
    {
        Edge& e=edges[G[x][i]];
        if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
        {
            e.flow+=f;
            edges[G[x][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}

//多个阶段,多次建立层次网络。
int Maxflow(int ss,int tt)
{
    int flow=0;
    while(BFS())
    {
        memset(cur,0,sizeof(cur));
        flow+=DFS(ss,INF);
    }
    return flow;
}


int main()
{
    int N,M,i,j;
    while(~scanf("%d%d",&N,&M))
    {

        edges.clear();
        for(int i=0; i<maxn; i++) G[i].clear();
        memset(In,0,sizeof(In));
        memset(Out,0,sizeof(Out));
        s=0;
        t=N+1;

        for(i=1; i<=M; i++)
        {
            int u,v,low,up;
            scanf("%d%d%d%d",&u,&v,&low,&up);
            AddEdge(u,v,low,up);
            In[v]=In[v]+low;
            Out[u]=Out[u]+low;
        }

        for(i=1; i<=N; i++)
        {
            AddEdge(i,t,0,Out[i]);
            AddEdge(s,i,0,In[i]);
        }

        Maxflow(s,t);

        int flag=1;
        for(i=0; i<edges.size(); i++)
            if(edges[i].from==s)
                if(edges[i].flow<edges[i].cap)
                {
                    flag=0;
                    break;
                }
        if(!flag) printf("NO\n");
        else
        {
            printf("YES\n");
            for(i=0; i<2*M; i++)
                if(i%2==0)
                    printf("%d\n",edges[i].flow+edges[i].low);
        }
    }
    return 0;
}



2、有源汇有上下界的最大流
解题思路:增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为oo的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边。
建图模型:源点s,终点d。超级源点ss,超级终点dd。首先判断是否存在满足所有边上下界的可行流,方法可以转化成无源汇有上下界的可行流问题。怎么转换呢?

增设一条从d到s没有下界容量为无穷的边,那么原图就变成了一个无源汇的循环流图。接下来的事情一样,超级源点ss连i(du[i]>0),i连超级汇点(du[i]<0),

对(ss,dd)进行一次最大流,当maxflow等于所有(du[]>0)之和时,有可行流,否则没有。

当有可行流时,删除超级源点ss和超级终点dd,再对(s,d)进行一次最大流,此时得到的maxflow则为题目的解。为什么呢?因为第一次maxflow()只是求得所有满足下界的流量,而残留网络(s,d)路上还有许多自由流(没有和超级源点和超级汇点连接的边)没有流满,所有最终得到的maxflow=(第一次流满下界的流+第二次能流通的自由流)。

讲解:http://blog.csdn.net/water_glass/article/details/6823741
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<string>  
  4. using namespace std;  
  5. #define maxM 50000  
  6. #define maxN 500  
  7. #define inf 1<<30  
  8. struct node{  
  9.     int u,v,f,next;  
  10. }edge[maxM];  
  11. int head[maxN],p,lev[maxN],cur[maxN];  
  12. int que[maxM],tre[maxN],up[maxN][50],low[maxN][50];  
  13. void init1(int n,int m){  
  14.     p=0,memset(head,-1,sizeof(head)),memset(tre,0,sizeof(tre));  
  15.     for(int i=0;i<=n;i++) for(int j=0;j<=m;j++)  
  16.         up[i][j]=inf,low[i][j]=0;  
  17. }  
  18. bool bfs(int s,int t){  
  19.     int qin=0,qout=0,u,i,v;  
  20.     memset(lev,0,sizeof(lev));  
  21.     lev[s]=1,que[qin++]=s;  
  22.     while(qout!=qin){  
  23.         u=que[qout++];  
  24.         for(i=head[u];i!=-1;i=edge[i].next){  
  25.             if(edge[i].f>0 && lev[v=edge[i].v]==0){  
  26.                 lev[v]=lev[u]+1,que[qin++]=v;  
  27.                 if(v==t) return 1;  
  28.             }  
  29.         }  
  30.     }  
  31.     return lev[t];  
  32. }  
  33. int dinic(int s,int t){  
  34.     int qin,u,i,k,f;  
  35.     int flow=0;  
  36.     while(bfs(s,t)){  
  37.         memcpy(cur,head,sizeof(head));  
  38.         u=s,qin=0;  
  39.         while(1){  
  40.             if(u==t){  
  41.                 for(k=0,f=inf;k<qin;k++)  
  42.                     if(edge[que[k]].f<f)  
  43.                         f=edge[que[i=k]].f;  
  44.                 for(k=0;k<qin;k++)  
  45.                     edge[que[k]].f-=f,edge[que[k]^1].f+=f;  
  46.                 flow+=f,u=edge[que[qin=i]].u;  
  47.             }  
  48.             for(i=cur[u];cur[u]!=-1;i=cur[u]=edge[cur[u]].next)  
  49.                 if(edge[i].f>0 && lev[u]+1==lev[edge[i].v]) break;  
  50.             if(cur[u]!=-1)  
  51.                 que[qin++]=cur[u],u=edge[cur[u]].v;  
  52.             else{  
  53.                 if(qin==0) break;  
  54.                 lev[u]=-1,u=edge[que[--qin]].u;  
  55.             }  
  56.         }  
  57.     }  
  58.     return flow;  
  59. }  
  60. void addedge(int u,int v,int f){  
  61.     edge[p].u=u,edge[p].v=v,edge[p].f=f,edge[p].next=head[u],head[u]=p++;  
  62.     edge[p].u=v,edge[p].v=u,edge[p].f=0,edge[p].next=head[v],head[v]=p++;  
  63. }  
  64. bool buit(int n,int m){  
  65.     for(int i=1;i<=n;i++)  
  66.         for(int j=1;j<=m;j++)  
  67.             if(low[i][j]>up[i][j]) return 0;  
  68.             else{  
  69.                 tre[i]-=low[i][j],tre[j+n]+=low[i][j];  
  70.                 addedge(i,j+n,up[i][j]-low[i][j]);  
  71.             }  
  72.     return 1;  
  73. }  
  74. void limitflow(int s,int t,int n,int m){  
  75.     int i,j,x,y;  
  76.     x=t+1,y=t+2;  
  77.     for(i=0;i<=t;i++){  
  78.         if(tre[i]>0) addedge(x,i,tre[i]);  
  79.         else if(tre[i]<0) addedge(i,y,-tre[i]);  
  80.     }  
  81.     addedge(t,s,inf);  
  82.     dinic(x,y);  
  83.     for(i=head[x];i!=-1;i=edge[i].next)  
  84.         if(edge[i].f){  
  85.             printf("IMPOSSIBLE\n\n"); return ;  
  86.         }  
  87.     for(i=head[t];i!=-1;i=edge[i].next)  
  88.         if(edge[i].v==s) break;  
  89.     if(i<0){  
  90.         printf("IMPOSSIBLE\n\n"); return;  
  91.     }  
  92.     for(i=1;i<=n;i++){  
  93.         for(j=1;j<m;j++)  
  94.             printf("%d ",edge[((i-1)*m+j)*2-1].f+low[i][j]);  
  95.         printf("%d\n",edge[i*m*2-1].f+low[i][j]);  
  96.     }  
  97.     printf("\n");  
  98. }  
  99. int main(){  
  100.     int cas,cas1,n,m,i,j,sum1,sum2;  
  101.     int u,v,d,f1,t1,f2,t2,s,t;  
  102.     char c[5];  
  103.     scanf("%d",&cas);  
  104.     for(int tt=1;tt<=cas;tt++){  
  105.         scanf("%d%d",&n,&m);  
  106.         s=0,t=n+m+1,sum1=0,sum2=0;  
  107.         init1(n,m);  
  108.         for(i=1;i<=n;i++) scanf("%d",&u),tre[s]-=u,tre[i]+=u,sum1+=u;;  
  109.         for(i=n+1;i<=n+m;i++) scanf("%d",&u),tre[i]-=u,tre[t]+=u,sum2+=u;  
  110.         scanf("%d",&cas1);  
  111.         while(cas1--){  
  112.             scanf("%d%d%s%d",&u,&v,c,&d);  
  113.             f1=t1=u,f2=t2=v;  
  114.             if(u==0) f1=1,t1=n;  
  115.             if(v==0) f2=1,t2=m;  
  116.             for(i=f1;i<=t1;i++)  
  117.                 for(j=f2;j<=t2;j++){  
  118.                     if(c[0]=='='){  
  119.                         low[i][j]=max(d,low[i][j]),up[i][j]=min(d,up[i][j]);  
  120.                     }else if(c[0]=='>'){  
  121.                         low[i][j]=max(d+1,low[i][j]);  
  122.                     }else if(c[0]=='<'){  
  123.                         up[i][j]=min(d-1,up[i][j]);  
  124.                     }  
  125.                 }  
  126.         }  
  127.         if(sum1==sum2 && buit(n,m)) limitflow(s,t,n,m);  
  128.         else printf("IMPOSSIBLE\n\n");  
  129.     }  
  130.     return 0;  
  131. }  
3、有源汇有上下界的最小流
解题思路:

   1、du[i]表示i节点的入流之和与出流之和的差。 

   2、增设超级源点st和超级汇点sd,连(st,du[i](为正)),(-du[i](为负),sd)。 ///增设超级源点和超级汇点,因为网络中规定不能有弧指向st,也不能有流量流出sd

   3、做一次maxflow()。

   4、源点(Sd)和起点(St)连一条容量为oo的边。

   5、再做一次maxflow()。

   6、当且仅当所有附加弧满载时有可行流,最后答案为flow[(Sd->St)^1],St到Sd最大流就是Sd到St最小流。
  

  1. /* 
  2. hdu 3157 
  3. poj 3801 
  4. 题意:一个电路板,上面有N个接线柱(标号1~N)   还有两个电源接线柱  +  - 
  5. 然后是 给出M个部件正负极的接线柱和最小电流 
  6. 求一个可以让所有部件正常工作的总电流  没有则输出impossible 
  7.  
  8. 其实就是一个 有源汇 有上下界 最小流 问题 
  9.  
  10. 处理有源汇有上下界最大流问题是: 
  11. 1.构造附加网络 
  12. 2.对ss、tt求最大流(ss、tt满流则有解) 
  13. 3.若有解,对s、t求最大流 
  14.  
  15. 而有源汇有上下界最小流问题则是: 
  16. 1.构造附加网络(不添加[t,s]边) 
  17. 2.对ss、tt求最大流 
  18. 3.添加[t,s]边 
  19. 4.对ss、tt求最大流 
  20. 5.若ss、tt满流,则[t,s]的流量就是最小流 
  21.  
  22. 这个代码大部分都是从别的题上摘过来的,注释有点乱 
  23. */  
  24. #include<stdio.h>  
  25. #include<string.h>  
  26. #define inf 0x7fffffff  
  27. struct edge//边    
  28. {    
  29.     int u,v,f,next,b,c;//边的 前节点 后节点 可用流 下条边的编号  原来边上流的上下界    
  30. }e[1500];    
  31. int head[70],in[70],s,t,ss,tt,yong,sum;  
  32. int n,m;  
  33. void ini()  
  34. {  
  35.     memset(head,-1,sizeof(head));  
  36.     yong=0;  
  37.     memset(in,0,sizeof(in));  
  38.     s=0,t=n+1,ss=t+1,tt=ss+1;//各节点编号的安排  
  39.     sum=0;  
  40. }  
  41. void adde(int from,int to,int xia,int shang)//加边    
  42. {   //加边    
  43.     e[yong].u=from,e[yong].v=to,e[yong].f=shang-xia,e[yong].b=xia,e[yong].c=shang;    
  44.     e[yong].next=head[from],head[from]=yong++;    
  45.     //同时加它的退边    
  46.     e[yong].u=to,e[yong].v=from,e[yong].f=0,e[yong].b=xia,e[yong].c=shang;    
  47.     e[yong].next=head[to],head[to]=yong++;    
  48. }   
  49. void build()  
  50. {  
  51.     int i;    
  52.     for(i=0;i<=t;++i)    
  53.     {    
  54.         if(in[i]>0)    
  55.             adde(ss,i,0,in[i]);    
  56.         else    
  57.         {    
  58.             adde(i,tt,0,-in[i]);    
  59.             sum+=(-in[i]);    
  60.         }    
  61.     }   
  62. }  
  63. int d[1000],num[1000];  
  64. int min(int a,int b){return a<b?a:b;}    
  65. int sap_gap(int u,int f,int s,int t)//递归sap    
  66. {    
  67.     if(u==t)    
  68.         return f;    
  69.     int i,v,mind=t,last=f,cost;    
  70.     for(i=head[u];i!=-1;i=e[i].next)    
  71.     {    
  72.         v=e[i].v;    
  73.         int flow=e[i].f;    
  74.         if(flow>0)//参考模版写的时候把flow写成了f    
  75.         {    
  76.             if(d[u]==d[v]+1)    
  77.             {    
  78.                 cost=sap_gap(v,min(last,flow),s,t);    
  79.                 e[i].f-=cost;    
  80.                 e[i^1].f+=cost;    
  81.                 last-=cost;    
  82.     
  83.                 if(d[s]>=t+1)    
  84.                     return f-last;    
  85.     
  86.                 if(last==0)    
  87.                     break;    
  88.             }    
  89.             if(d[v]<mind)    
  90.                 mind=d[v];    
  91.         }    
  92.     }    
  93.     
  94.     if(last==f)    
  95.     {    
  96.         --num[d[u]];    
  97.         if(num[d[u]]==0)    
  98.             d[s]=t+1;    
  99.         d[u]=mind+1;    
  100.         ++num[d[u]];    
  101.     }    
  102.     return f-last;    
  103. }    
  104. int max_f(int s,int t)  
  105. {  
  106.     int f=0;    
  107.     memset(d,0,sizeof(d));    
  108.     memset(num,0,sizeof(num));    
  109.     for(num[s]=t+1;d[s]<t+1;)    
  110.         f+=sap_gap(s,inf,s,t);    
  111.     return f;   
  112. }  
  113. int main()  
  114. {  
  115.     int i,dat,u,v,f1,f2,p;  
  116.     char from[10],to[10];  
  117.     while(scanf("%d%d",&n,&m),n+m)  
  118.     {  
  119.         ini();  
  120.         for(i=1;i<=m;++i)  
  121.         {  
  122.             scanf("%s%s%d",from,to,&dat);  
  123.             if(from[0]=='+') u=s;  
  124.             else sscanf(from,"%d",&u);  
  125.             if(to[0]=='-') v=t;  
  126.             else sscanf(to,"%d",&v);  
  127.             adde(u,v,dat,inf);  
  128.             in[u]-=dat,in[v]+=dat;  
  129.         }  
  130.         build();  
  131.   
  132.         f1=max_f(ss,tt);  
  133.         p=yong;  
  134.         adde(t,s,0,inf);  
  135.         f2=max_f(ss,tt);  
  136.         if(f1+f2!=sum) printf("impossible\n");  
  137.         else printf("%d\n",e[p^1].f);  
  138.     }  
  139.     return 0;  
  140. }  

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值