【POJ3422】Kaka's Matrix Travels
阿新 • • 發佈:2021-08-03
題目
解析:
由於一個點可以走多次,而且第二次走沒有分數,考慮拆點。每個點到它拆出來的點連兩條邊,一條的容量設成1,費用設為該格子分數的相反數。表示,這條邊只能走一次,且走這條邊能拿到分數;第二條的容量設成無窮大,費用設成\(0\),表示,這個格子可以重複走,但是沒有分數。然後在拆出來的點和它能到的點連邊,容量無窮大,費用為\(0\)就可以了。最後費用流增廣\(k\)次,得到的最小費用的相反數即為最大值。
code:
#include <iostream> #include <algorithm> #include <cstdio> #include <queue> using namespace std; const int Maxn=5005; const int Maxm=100005; const int inf=1e9; int n,m,size=-1,s,t,k,sum; int dis[Maxn],first[Maxn],v[Maxn],tmp[Maxn]; struct shu{int to,next,l,c;}e[Maxm<<1]; inline int get_int() { int x=0,f=1;char c; while(!isdigit(c) && c!='-') c=getchar(); if(c=='-') f=-1,c=getchar(); while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x*f; } inline int min(int x,int y){return x>y ? y : x;} inline void add(int x,int y,int l,int c) { e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].l=l,e[size].c=c; e[++size].next=first[y],first[y]=size,e[size].to=x,e[size].l=0,e[size].c=-c; } inline void init() { n=get_int(),k=get_int(),t=n*n*2+1; int len=n*n,x,pos; for(int i=s;i<=t;i++) first[i]=-1; for(int i=0;i<n;i++) for(int j=1;j<=n;j++) { x=get_int(),pos=i*n+j; add(pos,len+pos,1,-x),add(pos,len+pos,len,0); if(i<n-1) add(len+pos,pos+n,len,0); if(j<n) add(len+pos,pos+1,len,0); } add(s,1,inf,0),add(t-1,t,inf,0); } inline bool spfa() { queue<int>q; for(int i=s;i<=t;i++) dis[i]=inf,tmp[i]=first[i]; q.push(s),v[s]=1,dis[s]=0; while(!q.empty()) { int p=q.front();q.pop(),v[p]=0; for(register int u=first[p];~u;u=e[u].next) { int to=e[u].to; if(!e[u].l || dis[to]<=dis[p]+e[u].c) continue; dis[to]=dis[p]+e[u].c; if(!v[to]) v[to]=1,q.push(to); } } return dis[t]!=inf; } inline int dfs(int p,int flow) { if(p==t) return flow; int s=0;v[p]=1; for(register int &u=tmp[p];~u;u=e[u].next) { int to=e[u].to; if(!e[u].l || dis[to]!=dis[p]+e[u].c || v[to]) continue; int minn=dfs(to,min(flow-s,e[u].l)); e[u].l-=minn,e[u^1].l+=minn,s+=minn,sum+=minn*e[u].c; if(s==flow) break; } v[p]=0; return s; } inline void solve() { while(spfa()) while(dfs(s,inf)&&k) { k--; if(!k) return; } } int main() { freopen("lx.in","r",stdin); init(); if(k) solve(); cout<<-sum; return 0; }