POJ1459[Power Network]--最大流

【链接】
poj1459

【题目大意】
给你4个数n,np,nc,m,接下来m条电力输送线(路径),np个电站(起点)和nc个消费者(终点),以及起点,终点和路径的限定的流量,求最大流。

【解题报告】
最大流模板题。

EK:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=105,maxm=20505,INF=((1<<30)-1)*2+1;
int n,nc,np,m,tot,st,gl,ans,son[maxm],w[maxm],nxt[maxm],lnk[maxn],que[maxn],f[maxn],fa[maxn],fa_e[maxn];
bool vis[maxn];
inline int read_()
{
    int sum=0;
    char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') sum=sum*10+ch-48,ch=getchar();
    return sum;
}
void add_(int x,int y,int z)
{
    w[++tot]=z; son[tot]=y; nxt[tot]=lnk[x]; lnk[x]=tot;
}
int bfs_()
{
    memset(vis,0,sizeof(vis));
    memset(fa,0,sizeof(fa));
    que[1]=st; vis[st]=true; f[st]=INF;
    int hed=0,til=1;
    while (hed!=til)
    {
        int x=que[++hed];
        for (int j=lnk[x]; j; j=nxt[j])
         if (!vis[son[j]]&&w[j]>0)
          {
            vis[son[j]]=true; que[++til]=son[j];
            f[son[j]]=min(f[x],w[j]);
            fa[son[j]]=x; fa_e[son[j]]=j;
            if (son[j]==gl) return f[son[j]];
          }
    }
    return 0;
}
void change_(int x)
{
    int now=gl;
    while (now!=st)
    {
        int j=fa_e[now];
        w[j]-=x; w[j^1]+=x;
        now=fa[now];
    }
}
void work_()
{
    st=n; gl=n+1;
    memset(lnk,0,sizeof(lnk)); tot=1;
    for (int i=1; i<=m; i++)
    {
        int x=read_(),y=read_(),z=read_();
        add_(x,y,z); add_(y,x,0);
    }
    for (int i=1; i<=np; i++)
    {
        int x=read_(),z=read_();
        add_(st,x,z); add_(x,st,0);
    }
    for (int i=1; i<=nc; i++)
    {
        int x=read_(),z=read_();
        add_(x,gl,z); add_(gl,x,0);
    }
    ans=0;
    while (1)
    {
        int x=bfs_();
        if (x==0) break;
        change_(x); ans+=x;
    }
    printf("%d\n",ans);
}
int main()
{
    freopen("1459.in","r",stdin);
    freopen("1459.out","w",stdout);
    while (scanf("%d%d%d%d",&n,&np,&nc,&m)==4) work_();
    return 0;
}

Dinic:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=105,maxm=200005,INF=((1<<30)-1)*2+1;
int n,m,tot,np,nc,st,gl,dst[maxn],w[maxm],son[maxm],nxt[maxm],lnk[maxn],que[maxn],cur[maxn];
bool vis[maxn];
inline int Read()
{
    int res=0;
    char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=getchar();
    return res;
} 
void Add(int x,int y,int z)
{
    w[tot]=z; son[tot]=y; nxt[tot]=lnk[x]; lnk[x]=tot; tot++;
    w[tot]=0; son[tot]=x; nxt[tot]=lnk[y]; lnk[y]=tot; tot++;
}

bool Bfs(int s,int t)
{
    memset(vis,0,sizeof(vis));
    memset(dst,0,sizeof(dst));
    int hed=0,til=1; que[1]=s; vis[s]=1; dst[s]=0;
    while (hed!=til)
    {
        int x=que[++hed];
        for (int j=lnk[x]; ~j; j=nxt[j])
         if (!vis[son[j]]&&w[j]) vis[son[j]]=1,dst[son[j]]=dst[x]+1,que[++til]=son[j];
    }
    return vis[t];
}
int Dfs(int x,int t,int MIN)
{
    if (x==t||MIN==0) return MIN;
    int Flow=0;
    for (int &j=cur[x]; ~j; j=nxt[j])
     if (dst[x]+1==dst[son[j]])
      {
        int now=Dfs(son[j],t,min(MIN,w[j]));
        if (now)
         {
            w[j]-=now; w[j^1]+=now; Flow+=now; MIN-=now;
            if (!MIN) break;
         }
      }
    return Flow;
}
int MAXFlow(int s,int t)
{
    int Flow=0;
    while (Bfs(s,t))
    {
        memcpy(cur,lnk,sizeof(cur));
        Flow+=Dfs(s,t,INF);
    }
    return Flow;
}
void Work()
{
    st=n; gl=n+1; tot=0;
    memset(lnk,255,sizeof(lnk));
    for (int i=1,x,y,z; i<=m; i++) x=Read(),y=Read(),z=Read(),Add(x,y,z); 
    for (int i=1,y,z; i<=np; i++) y=Read(),z=Read(),Add(st,y,z);
    for (int i=1,x,z; i<=nc; i++) x=Read(),z=Read(),Add(x,gl,z);
    printf("%d\n",MAXFlow(st,gl));
}
int main()
{
    freopen("1459.in","r",stdin);
    freopen("1459.out","w",stdout);
    while (scanf("%d%d%d%d",&n,&np,&nc,&m)==4) Work();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值