POJ 1459&&3436

  两道比较基础的网络流题目,重点就是建图。

  1458:题意就是给你一些东西它们的数据,其中一些是发电站,还有一些是用户的家里,其中还有一些是中转站。让你求最大的输送电量。

  就是一道很基础的最大流题目,建超级源和汇,分别向发电站连边,从用户那连进边。

  具体的读入只需要写一下读优即可去括号。、

  CODE

#include<cstdio>
#include<cstring>
using namespace std;
const int N=105,INF=1e9;
struct edge
{
    int to,next,c;
}e[N*N*10];
int head[N],dep[N],q[N*10],n,np,nc,m,k,i,x,y,z,s,t;
inline void read(int &x)
{
    x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void write(int x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline void add(int x,int y,int z)
{
    e[++k].to=y; e[k].c=z; e[k].next=head[x]; head[x]=k;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline int BFS()
{
    memset(dep,0,sizeof(dep));
    int H=0,T=1;
    q[1]=s; dep[s]=1;
    while (H<T)
    {
        int now=q[++H];
        for (int i=head[now];i!=-1;i=e[i].next)
        if (!dep[e[i].to]&&e[i].c>0)
        {
            dep[e[i].to]=dep[now]+1;
            q[++T]=e[i].to;
        }
    }
    return dep[t];
}
inline int DFS(int now,int dist)
{
    if (now==t) return dist;
    int res=0;
    for (int i=head[now];i!=-1&&dist;i=e[i].next)
    if (dep[e[i].to]==dep[now]+1&&e[i].c>0)
    {
        int dis=DFS(e[i].to,min(dist,e[i].c));
        dist-=dis; res+=dis;
        e[i].c-=dis; e[i^1].c+=dis;
    }
    if (!res) dep[now]=0;
    return res;
}
inline int Dinic()
{
    int sum=0;
    while (BFS()) sum+=DFS(s,INF);
    return sum;
}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        memset(e,-1,sizeof(head));
        memset(head,-1,sizeof(head));
        read(np); read(nc); read(m); s=0; t=n+2; k=-1;
        for (i=1;i<=m;++i)
        {
            read(x); read(y); read(z);
            add(x+1,y+1,z); add(y+1,x+1,0);
        }
        for (i=1;i<=np;++i)
        {
            read(x); read(z);
            add(s,x+1,z); add(x+1,s,0);
        }
        for (i=1;i<=nc;++i)
        {
            read(x); read(z);
            add(x+1,t,z); add(t,s+1,0);
        }
        write(Dinic()); putchar('
');
    }
    return 0;
}

  3456:题意比较难理解,而且还要输出方案。

  大概是有n个工厂加工一种产品,其中每个产品都有p个部分。

  其中1表示必须要这个部件,0表示必须不要,2表示可有可无。

  然后给出所有工厂的单位时间内最多加工量和对输入输出的要求,让你求单位时间内最多加工多少个完整的产品(即所有部件都是1,刚开始所有的都是0)。

  思路:拆点,对于所有的工厂拆成两个点分别连入度和出度。对于所有工厂间若可以连成流水线就连一条INF的边。

  同时,由超级源向所有没有1的工厂连INF的边,所有没有1,2的工厂向超级汇连边。

  注意必须用scanf(雾),用read超时(滑稽)

  写了两个版本

  EK CODE

#include<cstdio>
#include<cstring>
using namespace std;
const int N=55<<1,P=15<<1,INF=1e9;
int f[N],pre[N],q[N],c[N][N],a[N][P],n,p,x,s,t,m;
inline void write(int x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline int BFS(void)
{
    memset(pre,-1,sizeof(pre));
    memset(f,0,sizeof(f));
    f[s]=INF; q[1]=s;
    int head=0,tail=1;
    while (head<tail)
    {
        int now=q[++head];
        for (register int i=s;i<=t;++i)
        if (pre[i]==-1&&c[now][i])
        {
            pre[i]=now;
            f[i]=min(f[now],c[now][i]);
            q[++tail]=i;
        }
    }
    return f[t];
}
inline int max_flow(void)
{
    int sum=0,inc;
    while (inc=BFS())
    {
        int now=t;
        while (now!=s)
        {
            c[pre[now]][now]-=inc;
            c[now][pre[now]]+=inc;
            now=pre[now];
        }
        sum+=inc;
    }
    return sum;
}
int main()
{
    register int i,j,k;
    while (scanf("%d%d",&p,&n)!=EOF)
    {
        memset(c,0,sizeof(c));
        s=0; t=2*n+1; m=0;
        for (i=1;i<=n;++i)
        {
            scanf("%d",&x);
            c[i][i+n]=x; 
            bool flag_0=1,flag_1=1;
            for (j=1;j<=p;++j)
            {
                scanf("%d",&a[i][j]);
                if (a[i][j]==1) flag_0=0;
            }
            for (j=1;j<=p;++j)
            {
                scanf("%d",&a[i][j+p]);
                if (a[i][j+p]!=1) flag_1=0;
            }
            if (flag_0) c[s][i]=INF;
            if (flag_1) c[i+n][t]=INF;
        }
        for (i=1;i<=n;++i)
        for (j=1;j<=n;++j)
        {
            bool flag=1;
            for (k=1;k<=p;++k)
            if (a[i][k+p]+a[j][k]==1) { flag=0; break; }
            if (flag) c[i+n][j]=INF;
        }
        write(max_flow()); putchar(' ');
        for (i=n+1;i<=2*n;++i)
        for (j=1;j<=n;++j)
        if (c[j][i]&&i-n!=j) ++m;
        write(m); putchar('
');
        for (i=n+1;i<=2*n;++i)
        for (j=1;j<=n;++j)
        if (c[j][i]&&i-n!=j) write(i-n),putchar(' '),write(j),putchar(' '),write(c[j][i]),putchar('
');
    }
    return 0;
}

  Dinic CODE

#include<cstdio>
#include<cstring>
using namespace std;
const int N=55<<1,P=15<<1,INF=1e9;
struct data
{
    int to,next,c;
}e[N*N];
int head[N],dep[N],q[N],a[N][P],n,p,x,s,t,m,tot;
inline void write(int x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline void add(int x,int y,int z)
{
    e[++tot].to=y; e[tot].c=z; e[tot].next=head[x]; head[x]=tot;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline bool BFS(void)
{
    memset(dep,0,sizeof(dep));
    q[1]=s; dep[s]=1;
    int H=0,T=1;
    while (H<T)
    {
        int now=q[++H];
        for (register int i=head[now];i!=-1;i=e[i].next)
        if (!dep[e[i].to]&&e[i].c)
        {
            dep[e[i].to]=dep[now]+1;
            q[++T]=e[i].to;
        }
    }
    return dep[t];
}
inline int DFS(int now,int dist)
{
    if (now==t) return dist;
    int res=0;
    for (register int i=head[now];i!=-1&&dist;i=e[i].next)
    if (dep[e[i].to]==dep[now]+1&&e[i].c)
    {
        int dis=DFS(e[i].to,min(e[i].c,dist));
        dist-=dis; res+=dis;
        e[i].c-=dis; e[i^1].c+=dis;
    }
    if (!res) dep[now]=0;
    return res;
}
inline int Dinic(void)
{
    int sum=0;
    while (BFS()) sum+=DFS(s,INF);
    return sum;
}
inline int abs(int x)
{
    return x>0?x:-x;
}
int main()
{
    register int i,j,k;
    while (scanf("%d%d",&p,&n)!=EOF)
    {
        memset(e,-1,sizeof(e));
        memset(head,-1,sizeof(head));
        s=0; t=2*n+1; m=0; tot=-1;
        for (i=1;i<=n;++i)
        {
            scanf("%d",&x);
            add(i,i+n,x); add(i+n,i,0);
            bool flag_0=1,flag_1=1;
            for (j=1;j<=p;++j)
            {
                scanf("%d",&a[i][j]);
                if (a[i][j]==1) flag_0=0;
            }
            for (j=1;j<=p;++j)
            {
                scanf("%d",&a[i][j+p]);
                if (a[i][j+p]!=1) flag_1=0;
            }
            if (flag_0) add(s,i,INF),add(i,s,0);
            if (flag_1) add(i+n,t,INF),add(t,i+n,0);
        }
        for (i=1;i<=n;++i)
        for (j=1;j<=n;++j)
        {
            bool flag=1;
            for (k=1;k<=p;++k)
            if (a[i][k+p]+a[j][k]==1) { flag=0; break; }
            if (flag) add(i+n,j,INF),add(j,i+n,0);
        }
        write(Dinic()); putchar(' ');
        for (i=1;i<=tot;i+=2)
        if (e[i].c&&abs(e[i].to-e[i-1].to)!=n&&e[i].to!=s&&e[i-1].to!=t) ++m;
        write(m); putchar('
');
        for (i=1;i<=tot;i+=2)
        if (e[i].c&&abs(e[i].to-e[i-1].to)!=n&&e[i].to!=s&&e[i-1].to!=t) write(e[i].to-n),putchar(' '),write(e[i-1].to),putchar(' '),write(e[i].c),putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjjsb/p/8671854.html