【BZOJ】3698:XWW的难题-上下界网络流
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ】3698:XWW的难题-上下界网络流
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題解
下界為各數(shù)下取整的值,取差建立超級源匯點SS,TT跑一遍dinic,先判斷是否可以滿流,然后再跑原圖,ans*3(原值算一遍,右邊算一遍,下邊算一遍)
詳見代碼
代碼
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define inf 0x7fffffff #define db double using namespace std; db a[102][102]; int n,S,T,SS,TT,tot=1,in[225],d[225],sum,ans; int head[250],cur[250],to[1000005],nxt[1000005],w[1000005]; queue<int>Q; inline void lk(int u,int v,int val) {to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=val;} inline int imin(int x,int y){return x>y?y:x;} inline void build() {int i,j;for(i=1;i<=n;++i){if(a[i][n]!=(int)a[i][n]) lk(S,i,1),lk(i,S,0);in[S]-=(int)a[i][n];in[i]+=(int)a[i][n]; }for(i=1;i<=n;++i){if(a[n][i]!=(int)a[n][i]) lk(i+n,T,1),lk(T,i+n,0);in[i+n]-=(int)a[n][i];in[T]+=(int)a[n][i];}for(i=1;i<n;++i)for(j=1;j<n;++j){if(a[i][j]!=(int)a[i][j]) lk(i,j+n,1),lk(j+n,i,0);in[i]-=(int)a[i][j];in[j+n]+=(int)a[i][j];}for(i=1;i<=TT;++i){if(in[i]>0){sum+=in[i];lk(SS,i,in[i]);lk(i,SS,0);}else if(in[i]<0)lk(i,TT,-in[i]),lk(TT,i,0);} }inline bool bfs(int s,int t) {int I,J;for(I=1;I<=TT;++I) d[I]=-1;d[s]=0;Q.push(s);int x;while(!Q.empty()){x=Q.front();Q.pop();for(I=head[x];I;I=nxt[I]){J=to[I];if(d[J]==-1 && w[I]){d[J]=d[x]+1;Q.push(J);}}}return d[t]!=-1?; }inline int dfs(int s,int t,int f) {if(s==t) return f;int ss=0,ret;for(int i=cur[s],j;i;i=nxt[i]){j=to[i];if(d[j]==d[s]+1 && w[i]){ret=f-ss;ret=dfs(j,t,imin(ret,w[i]));w[i]-=ret;w[i^1]+=ret;if(w[i]) cur[s]=i;ss+=ret;if(ss==f) return f;}}if(!ss) d[s]=-1;return ss; }inline void dinic(int s,int t) {while(bfs(s,t)){for(int i=1;i<=TT;++i) cur[i]=head[i];ans+=dfs(s,t,inf);} }int main(){int i,j;scanf("%d",&n);for(i=1;i<=n;++i)for(j=1;j<=n;++j) scanf("%lf",&a[i][j]);S=(n<<1)+1;T=S+1;SS=T+1;TT=SS+1;build();lk(T,S,inf);lk(S,T,0);dinic(SS,TT);if(ans!=sum){printf("NO\n");return 0;}ans=0;dinic(S,T);printf("%d\n",ans*3); }總結
以上是生活随笔為你收集整理的【BZOJ】3698:XWW的难题-上下界网络流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解除当前设置不允许下载该文件
- 下一篇: viterbi-algorithm 维特