洛谷3973 TJOI2015線性代數(最小割+思維)
阿新 • • 發佈:2018-12-24
size fine clas add map ont pop 獲取 矩陣乘法 的代價。
然後\((i,j) \rightarrow i,(i,j)\rightarrow j\)
流量是\(inf\)
因為依賴關系沒法取消
感覺要做出來這個題,需要一定的線代芝士
首先,我們來觀察這個柿子。
我們將\(B\)的權值看作是收益的話,\(C\)的權值就是花費。
根據矩陣乘法的原理,只有當\(a[i]和a[j]\)都為\(1\)的時候,才能夠獲取到\(a[i][j]\)代價,而把\(a[i]\)弄成1,又會付出\(c[i]\)的代價。
那這不就是一個經典的最大全閉合子圖模型嗎?
我們令\(S \rightarrow (i,j)\)這個坐標對應的點。流量是\(b[i][j]\),表示割去這個邊,就舍棄了\(b[i][j]\)的收益
然後\(i\rightarrow t\),流量是\(c[i]\),表示如果這一位是1,要付出\(c[i]\)
然後\((i,j) \rightarrow i,(i,j)\rightarrow j\)
流量是\(inf\)
因為依賴關系沒法取消
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> #include<set> #define mk make_pair #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)) {if (ch==‘-‘) f=-1;ch=getchar();} while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } const int maxn = 303003; const int maxm = 2e6+1e2; const int inf = 1e9; int point[maxn],nxt[maxm],to[maxm],val[maxm]; int cnt=1,n,m; int h[maxn]; int b[610][610]; int c[510]; void addedge(int x,int y,int w) { nxt[++cnt]=point[x]; to[cnt]=y; val[cnt]=w; point[x]=cnt; } void insert(int x,int y,int w) { addedge(x,y,w); addedge(y,x,0); } int s,t; queue<int> q; bool bfs(int s) { memset(h,-1,sizeof(h)); h[s]=0; q.push(s); while (!q.empty()) { int x = q.front(); q.pop(); for (int i=point[x];i;i=nxt[i]) { int p = to[i]; if (h[p]==-1 && val[i]>0) { h[p]=h[x]+1; q.push(p); } } } //cout<<1<<endl; if(h[t]==-1) return false; return true; } int dfs(int x,int low) { if (x==t ||low==0) return low; int totflow=0; for (int i=point[x];i;i=nxt[i]) { int p=to[i]; if (val[i]>0 &&h[p]==h[x]+1) { int tmp = dfs(p,min(low,val[i])); val[i]-=tmp; val[i^1]+=tmp; low-=tmp; totflow+=tmp; if (low==0) return totflow; } } if (low>0) h[x]=-1; return totflow; } int dinic() { int ans=0; while (bfs(s)) { ans=ans+dfs(s,inf); } return ans; } int main() { n=read(); s=maxn-10; t=s+1; int sum=0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { b[i][j]=read(); sum+=b[i][j]; insert(s,(i-1)*n+j,b[i][j]); } for (int i=1;i<=n;i++) c[i]=read(),insert(i+n*n,t,c[i]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { insert((i-1)*n+j,i+n*n,inf); insert((i-1)*n+j,j+n*n,inf); } sum-=dinic(); cout<<sum; return 0; }
洛谷3973 TJOI2015線性代數(最小割+思維)