【codevs1227】方格取数2 费用流(EK)

题目描述 Description

给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

输入描述 Input Description

第一行两个数n,k(1<=n<=50, 0<=k<=10)

接下来n行,每行n个数,分别表示矩阵的每个格子的数

输出描述 Output Description

一个数,为最大和

样例输入 Sample Input

3 1

1 2 3

0 2 1

1 4 2

样例输出 Sample Output

11

数据范围及提示 Data Size & Hint

1<=n<=50, 0<=k<=10

把每个节点拆成两个,分别为ai和bi

ai向bi连边,费用为权值,容量为1
再连边,费用为0,容量为k,保证联通

其他能到达i号点的点,向ai连边,费用为0,流量为k。向外连边则用bi向外连。

新建节点s向< 1,1 >连边,费用为0,流量为k。
新建节点e向< n,n >连边,费用为0,流量为k。

然后s向e做最大费用流。

然后我想问,为什么我的dinic比EK慢!!dinic会T两个点!!

代码(EK):

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int SZ=100010;
const int INF=1000000000;

int head[SZ],nxt[SZ],tot=1;

struct edge{
    int f,t,d,c;
}l[SZ];

void build(int f,int t,int d,int c)
{
    l[++tot].t=t;
    l[tot].f=f;
    l[tot].d=d;
    l[tot].c=c;
    nxt[tot]=head[f];
    head[f]=tot;
}

int s,e,n;

queue<int> q;

int pre[SZ],f[SZ],dist[SZ];
bool use[SZ];

bool spfa(int &cost,int &flow)
{
    for(int i=1;i<=n;i++) dist[i]=-INF;
    f[s]=INF;
    dist[s]=0;
    q.push(s);
    use[s]=1;
    while(q.size())
    {
        int f=q.front(); q.pop();
        use[f]=0;
        for(int i=head[f];i;i=nxt[i])
        {
            int v=l[i].t;
            if(l[i].c && dist[v] < dist[f] + l[i].d)
            {
                dist[v] = dist[f] + l[i].d;
                ::f[v] = min(::f[f],l[i].c);
                pre[v] = i;

                if(!use[v])
                {
                    use[v]=1;
                    q.push(v);
                }
            }
        }
    }
    if(dist[e]==-INF) return false;

    flow += f[e];
    cost += dist[e] * f[e];

    for(int i=e;i!=s;i=l[pre[i]].f)
    {
        l[pre[i]].c -= f[e];
        l[pre[i]^1].c += f[e];
    }
    return true;
}

int getnode(int x,int y)
{
    return (x-1)*n+y;
}

int EK()
{
    int cost=0,flow=0;
    while(spfa(cost,flow));
    return cost;
}


int main()
{
    int m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);

            int sa = getnode(i,j),sb = getnode(i,j)+n*n;
            build(sa,sb,x,1);   build(sb,sa,-x,0);
            build(sa,sb,0,m);   build(sb,sa,0,0);

            if(i != n)
            {
                int ea = getnode(i+1,j);
                build(sb,ea,0,m); build(ea,sb,0,0);
            }
            if(j != n)
            {
                int ea = getnode(i,j+1); 
                build(sb,ea,0,m); build(ea,sb,0,0);
            }
        }
    }   
    s = n*n*2+1; e = n*n*2+2;
    build(s,1,0,m); build(1,s,0,0);
    build(n*n*2,e,0,m); build(e,n*n*2,0,0);
    n = n*n*2+2;
    printf("%lld",EK());

    return 0;
}

dinic:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef long long LL;

const int SZ=1000010;
const int INF=1000000000;

int head[SZ],nxt[SZ],tot=1,n,m;

struct edge{
    int t,c;
    LL d;
}l[SZ];

void build(int f,int t,LL d,int c)
{
    l[++tot].t=t;
    l[tot].d=d;
    l[tot].c=c;
    nxt[tot]=head[f];
    head[f]=tot;
}

queue<int> q;

bool use[SZ];

int dist[SZ],s,e;

bool spfa()
{
    for(int i = 1;i <= n;i ++) dist[i] = -INF;
    dist[s] = 0;
    use[s] = 1;
    q.push(s);
    while(q.size())
    {
        int f=q.front(); q.pop();
        use[f] = 0;
        for(int i = head[f];i;i = nxt[i])
        {
            int v = l[i].t;
            if(l[i].c && dist[v] < dist[f] + l[i].d)
            {
                dist[v] = dist[f] + l[i].d;
                if(!use[v])
                {
                    use[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    if(dist[e] == -INF) return false;
    return true;
}

bool vis[SZ];

int dfs(int u,int flow,LL &cost)
{
    if(u == e || flow == 0) return flow;
    int ans = 0;
    for(int i = head[u];i;i = nxt[i])
    if(!vis[i])
    {
        int v = l[i].t;
        if(l[i].c && dist[v] == dist[u] + l[i].d)
        {
            vis[i] = 1;
            int f = dfs(v,min(flow - ans,l[i].c),cost);
            if(f > 0)
            {
                cost += l[i].d * l[i].c;
                l[i].c -= f;
                l[i^1].c += f;
                ans += f;
                if(flow == ans) break;
            }
            vis[i] = 0;
        }
    }
    if(ans == 0) dist[u] = INF;
    return ans;
}


LL dinic()
{
    LL cost = 0;
    while(spfa())
    {
        int tmp = dfs(s,INF,cost);
        if(tmp == 0) break;
        memset(vis,0,sizeof(vis));
    }
    return cost;
}

int getnode(int x,int y)
{
    return (x-1)*n+y;
}


int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);

            int sa = getnode(i,j),sb = getnode(i,j)+n*n;
            build(sa,sb,x,1);   build(sb,sa,-x,0);
            build(sa,sb,0,m);   build(sb,sa,0,0);

            if(i != n)
            {
                int ea = getnode(i+1,j);
                build(sb,ea,0,m); build(ea,sb,0,0);
            }
            if(j != n)
            {
                int ea = getnode(i,j+1); 
                build(sb,ea,0,m); build(ea,sb,0,0);
            }
        }
    }   
    s = n*n*2+1; e = n*n*2+2;
    build(s,1,0,m); build(1,s,0,0);
    build(n*n*2,e,0,m); build(e,n*n*2,0,0);
    n = n*n*2+2;
    printf("%lld",dinic());

    return 0;
}

你可能感兴趣的:(网络流)