生活随笔
收集整理的這篇文章主要介紹了
XWW的难题(bzoj 3698)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Description
XWW是個影響力很大的人,他有很多的追隨者。這些追隨者都想要加入XWW教成為XWW的教徒。但是這并不容易,需要通過XWW的考核。
XWW給你出了這么一個難題:XWW給你一個N*N的正實數(shù)矩陣A,滿足XWW性。
稱一個N*N的矩陣滿足XWW性當且僅當:(1)A[N][N]=0;(2)矩陣中每行的最后一個元素等于該行前N-1個數(shù)的和;(3)矩陣中每列的最后一個元素等于該列前N-1個數(shù)的和。
現(xiàn)在你要給A中的數(shù)進行取整操作(可以是上取整或者下取整),使得最后的A矩陣仍然滿足XWW性。同時XWW還要求A中的元素之和盡量大。
Input
第一行一個整數(shù)N,N ≤ 100。
接下來N行每行包含N個絕對值小于等于1000的實數(shù),最多一位小數(shù)。
Output
輸出一行,即取整后A矩陣的元素之和的最大值。無解輸出No。
Sample Input
4
3.1 6.8 7.3 17.2
9.6 2.4 0.7 12.7
3.6 1.2 6.5 11.3
16.3 10.4 14.5 0
Sample Output
129
HINT
?
【數(shù)據(jù)規(guī)模與約定】
有10組數(shù)據(jù),n的大小分別為10,20,30...100。
【樣例說明】
樣例中取整后滿足XWW性的和最大的矩陣為:
3 7 8 18
10 3 0 13
4 1 7 12
17 11 15 0
/*上下界最大流。建立源點SS,從SS向i連一條上下界為(floor(a[i][n]),ceil(a[i][n]))的邊;建立源點TT,從i'向TT連一條上下界為(floor(a[n][i]),ceil(a[n][i]))的邊;建立i->i'上下界為(floor(a[i][j]),ceil(a[i][j]))的邊。跑上下界最大流。
*/
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define N 210
#define M 21000
#define inf 1000000000
using namespace std;
int down[N][N],up[N][N],head[N],dis[N],s[N],n,cnt=
1,SS,TT,S,T;
struct node{
int v,f,pre;}e[M];
queue<
int>
q;
void add(
int u,
int v,
int f){e[++cnt].v=v;e[cnt].f=f;e[cnt].pre=head[u];head[u]=
cnt;e[++cnt].v=u;e[cnt].f=
0;e[cnt].pre=head[v];head[v]=
cnt;
}
bool bfs(){memset(dis,-
1,
sizeof(dis));q.push(S);dis[S]=
0;while(!
q.empty()){int u=
q.front();q.pop();for(
int i=head[u];i;i=
e[i].pre){if(!e[i].f||dis[e[i].v]!=-
1)
continue;dis[e[i].v]=dis[u]+
1;q.push(e[i].v);}}return dis[T]!=-
1;
}
int dinic(
int x,
int f){int rest=
f;if(x==T)
return f;for(
int i=head[x];i;i=
e[i].pre){if(!e[i].f||dis[e[i].v]!=dis[x]+
1)
continue;int t=
dinic(e[i].v,min(rest,e[i].f));e[i].f-=t;e[i^
1].f+=t;rest-=
t;}if(rest==f) dis[x]=-
1;return f-
rest;
}
int main(){scanf("%d",&
n);SS=n*
2+
1;TT=n*
2+
2;S=n*
2+
3;T=n*
2+
4;for(
int i=
1;i<=n;i++
)for(
int j=
1;j<=n;j++
){double x;scanf(
"%lf",&
x);down[i][j]=
int(x);up[i][j]=
int(x+
0.99);}for(
int i=
1;i<n;i++
){if(down[i][n]!=up[i][n]) add(SS,i,
1);if(down[n][i]!=up[n][i]) add(i+n,TT,
1);s[SS]+=down[i][n];s[i]-=
down[i][n];s[i+n]+=down[n][i];s[TT]-=
down[n][i];}for(
int i=
1;i<n;i++
)for(
int j=
1;j<n;j++
){if(down[i][j]!=up[i][j]) add(i,j+n,
1);s[i]+=down[i][j];s[j+n]-=
down[i][j];}int tot=
0;for(
int i=
1;i<=T;i++
){if(s[i]>
0) add(i,T,s[i]),tot+=
s[i];if(s[i]<
0) add(S,i,-
s[i]);}add(TT,SS,inf);int maxflow=
0;while(bfs()) maxflow+=
dinic(S,inf);if(maxflow!=tot) {printf(
"No");
return 0;}maxflow=
0;S=SS;T=
TT;while(bfs()) maxflow+=
dinic(S,inf);printf("%d",maxflow*
3);return 0;
} ?
轉(zhuǎn)載于:https://www.cnblogs.com/harden/p/6629156.html
總結(jié)
以上是生活随笔為你收集整理的XWW的难题(bzoj 3698)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。