LUOGU 4014 24 distribution network flow problem

Copyright: https: //blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/91352783

title

LUOGU 4014
Title Description

There are n n pieces of work to be assigned to individuals to do. Person i do benefits arising from the work piece as the j c i j c_{ij} . Try to design a piece of work will be assigned to n n individual distribution plan to do to make maximum total benefits generated.

Input and output format
input format:

The first line of the file has a positive integer n, n expressed the job to be assigned to n individuals do.
The following n rows, each row having n integers c i j c_{ij} , I represents the personal benefit of doing the job j is generated c i j c_{ij}

Output formats:

Two lines are the smallest total output efficiency and maximum total benefit.

Input Output Sample
Input Sample # 1:

5
2 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1

Output Sample # 1:

5
14

Explanation

1 n 100 1 \ leq n \ leq 100
a repair man only one workpiece

analysis

After writing so long network flow 24 questions, the first time to run into exactly the same model two questions, distribution and transportation problems really be one pair of wonderful work.

Construction Plan is exactly the same:

  • 1. source point s Source s to warehouse Storehouse i Warehouse i connection capacity 1 1 at a cost of 0 0 edge.
  • 2. warehouse Storehouse i Warehouse i to pin Sell point j Point of sale j connection capacity 1 1 at a cost of c [ i ] [ j ] c[i][j]
  • 3. pin Sell point j Point of sale j to exchange point t Meeting Point t connection capacity 1 1 at a cost of 0 0 edge.

Run a minimum cost maximum flow, easy to complete the first task.
The second task as long empty map, and then reconnect to cost c [ i ] [ j ] −c[i][j] side to.

As for why they are both capacities 1 1 ? That's because a person can only repair a workpiece, a workpiece can only be a repair person, that can only be used once.

This time it is really easy.

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10,maxm=210,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],cost[maxn<<1],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
    ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>q;q.push(s);
    dist[s]=0,vis[s]=1,incf[s]=1<<30;
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x]; i; i=Next[i])
        {
            if (!edge[i]) continue;
            int y=ver[i];
            if (dist[y]>dist[x]+cost[i])
            {
                dist[y]=dist[x]+cost[i];
                incf[y]=min(incf[x],edge[i]);
                pre[y]=i;
                if (!vis[y]) q.push(y),vis[y]=1;
            }
        }
    }
    if (dist[t]==inf) return false;
    else return true;
}

long long maxflow,ans;
inline void update()
{
    int x=t;
    while (x!=s)
    {
        int i=pre[x];
        edge[i]-=incf[t];
        edge[i^1]+=incf[t];
        x=ver[i^1];
    }
    maxflow+=incf[t];
    ans+=dist[t]*incf[t];
}

int n,c[maxm][maxm];
inline void build(int off)
{
	memset(head,0,sizeof(head));
	len=1;
	ans=maxflow=0;
	s=0,t=n<<1|1;
	for (int i=1; i<=n; ++i) add(s,i,1,0);
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=n; ++j) add(i,j+n,1,c[i][j]*off);
	for (int i=1; i<=n; ++i) add(i+n,t,1,0);
}

int main()
{
	read(n);
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=n; ++j) read(c[i][j]);

	build(1);
	while (spfa()) update();
	write(ans),puts("");

	build(-1);
	while (spfa()) update();
	write(-ans),puts("");
	return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/91352783