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 . 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 , I represents the personal benefit of doing the job j is generated 。
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
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. to connection capacity at a cost of edge.
- 2. to connection capacity at a cost of 。
- 3. to connection capacity at a cost of 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
side to.
As for why they are both capacities ? 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;
}