题目链接:https://www.luogu.com.cn/problem/P4014

网络流24题-5  分配问题_c++

 

 网络流24题-5  分配问题_#include_02

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=211,M=4e4+11,inf=1<<29;
  4 int n,a[N][N],st,ed,maxflow,maxx,minn;
  5 int to[M],nxt[M],c[M],w[M],edge,head[N];
  6 int dis[N],incf[N],pre[N];
  7 bool vis[N];
  8 
  9 inline int re_ad() {
 10     char ch=getchar(); int x=0,f=1;
 11     while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
 12     while('0'<=ch && ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
 13     return x*f;
 14 }
 15 
 16 inline void addedge(int x,int y,int cc,int ww) {
 17     ++edge,to[edge]=y,nxt[edge]=head[x],c[edge]=cc,w[edge]=ww,head[x]=edge;
 18     ++edge,to[edge]=x,nxt[edge]=head[y],c[edge]=0,w[edge]=-ww,head[y]=edge;
 19 }
 20 
 21 inline bool SPFA_Min() {
 22     memset(vis,false,sizeof(vis));
 23     memset(dis,0x3f,sizeof(dis));
 24     memset(pre,0,sizeof(pre));
 25     memset(incf,0x3f,sizeof(incf));
 26     queue<int> q;
 27     q.push(st);
 28     dis[st]=0,vis[st]=true;
 29     while(!q.empty()) {
 30         int u=q.front(),v;
 31         vis[u]=false,q.pop();
 32         for(int i=head[u];i;i=nxt[i]) {
 33             if(!c[i]) continue;
 34             v=to[i];
 35             if(dis[u]+w[i]<dis[v]) {
 36                 dis[v]=dis[u]+w[i];
 37                 incf[v]=min(incf[u],c[i]);
 38                 pre[v]=i;
 39                 if(!vis[v]) vis[v]=true,q.push(v);
 40             }
 41         }
 42     }
 43 //    printf("min:dis[ed]: %d\n",dis[ed]);
 44     if(dis[ed]==0x3f3f3f3f) return false;
 45     return true;
 46 }
 47 
 48 inline void Update_Min() {
 49 //    printf("awa\n");
 50     int lj=ed,i;
 51     while(lj!=st) {
 52         i=pre[lj];
 53         c[i]-=incf[ed],c[i^1]+=incf[ed];
 54         lj=to[i^1];
 55     }
 56     maxflow+=incf[ed];
 57     minn+=dis[ed]*incf[ed];
 58 }
 59 
 60 inline bool SPFA_Max() {
 61     memset(vis,false,sizeof(vis));
 62     memset(dis,0xcf,sizeof(dis));
 63     memset(pre,0,sizeof(pre));
 64     memset(incf,0x3f,sizeof(incf));
 65     queue<int> q;
 66     q.push(st);
 67     dis[st]=0,vis[st]=true;
 68 //    printf("ed: %d\n",dis[ed]);
 69     while(!q.empty()) {
 70         int u=q.front(),v;
 71 //        printf("max:u: %d %d\n",u,dis[u]);
 72         vis[u]=false,q.pop();
 73         for(int i=head[u];i;i=nxt[i]) {
 74             if(!c[i]) continue;
 75             v=to[i];
 76             if(dis[u]+w[i]>dis[v]) {
 77                 dis[v]=dis[u]+w[i];
 78                 incf[v]=min(incf[u],c[i]);
 79                 pre[v]=i;
 80                 if(!vis[v]) vis[v]=true,q.push(v);
 81             }
 82         }
 83     }
 84 //    printf("max:dis[ed]: %d\n",dis[ed]);
 85     if(dis[ed]==0xcfcfcfcf) return false;
 86     return true;
 87 }
 88 
 89 inline void Update_Max() {
 90     int lj=ed,i;
 91     while(lj!=st) {
 92         i=pre[lj];
 93         c[i]-=incf[ed],c[i^1]+=incf[ed];
 94         lj=to[i^1];
 95     }
 96     maxflow+=incf[ed];
 97     maxx+=dis[ed]*incf[ed];
 98 }
 99 
100 int main()
101 {
102     n=re_ad();
103     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=re_ad();
104     st=0,ed=n*2+1,edge=1,maxflow=0;
105     memset(head,0,sizeof(head));
106     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) addedge(i,j+n,1,a[i][j]);
107     for(int i=1;i<=n;++i) addedge(st,i,1,0),addedge(i+n,ed,1,0);
108     while(SPFA_Min()) Update_Min();
109 //    printf("endif:min:%d\n",minn);
110     
111     st=0,ed=n*2+1,edge=1,maxflow=0;
112     memset(head,0,sizeof(head));
113     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) addedge(i,j+n,1,a[i][j]);
114     for(int i=1;i<=n;++i) addedge(st,i,1,0),addedge(i+n,ed,1,0);
115     while(SPFA_Max()) Update_Max();
116     printf("%d\n%d\n",minn,maxx);
117     return 0;
118 }