生活随笔
收集整理的這篇文章主要介紹了
【bzoj3698】【XWW的难题】【有上下界的网络流】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Description
XWW是個(gè)影響力很大的人,他有很多的追隨者。這些追隨者都想要加入XWW教成為XWW的教徒。但是這并不容易,需要通過XWW的考核。
XWW給你出了這么一個(gè)難題:XWW給你一個(gè)N*N的正實(shí)數(shù)矩陣A,滿足XWW性。
稱一個(gè)N*N的矩陣滿足XWW性當(dāng)且僅當(dāng):(1)A[N][N]=0;(2)矩陣中每行的最后一個(gè)元素等于該行前N-1個(gè)數(shù)的和;(3)矩陣中每列的最后一個(gè)元素等于該列前N-1個(gè)數(shù)的和。
現(xiàn)在你要給A中的數(shù)進(jìn)行取整操作(可以是上取整或者下取整),使得最后的A矩陣仍然滿足XWW性。同時(shí)XWW還要求A中的元素之和盡量大。
Input
第一行一個(gè)整數(shù)N,N ≤ 100。
接下來N行每行包含N個(gè)絕對值小于等于1000的實(shí)數(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
題解: ? ? ? ? ? ? n行n列分別看成n個(gè)點(diǎn),s為源點(diǎn),t為匯點(diǎn). ? ? ? ? ? ? s向每一行i連a[i][n]的邊. ? ? ? ? ? ? 每一列i向t連a[n][i]的邊. ? ? ? ? ? ? 每一行i向每一行j連a[i][j]的邊. ? ? ? ? ? ? 這里的a值是有取值范圍的.所以就是求有源有匯有上下界的最大流. ? ? ? ? ? ? 具體求法就是 ? ? ? ? ? ? ? ?1.從t向s連一條inf的邊,把圖變成無源無匯, ? ? ? ? ? ? ? ?2.新建源匯S,T,按有上下界的方法建圖. ? ? ? ? ? ? ? ?3.求S,T的最大流,檢驗(yàn)如果S連出去的邊都滿流代表合法. ? ? ? ? ? ? ? ?4.求s,t的最大流即是答案. ? ? ? ? ? ?注意最后答案要乘3,因?yàn)橐粋€(gè)點(diǎn)會(huì)在它這個(gè)位置,這一行的末尾,這一列的末尾算三次. ?代碼: #include<iostream>
#include<cstdio>
#include<cstring>
#define N 300
#define M 40000
#define inf 210000000
using namespace std;
int point[N],next[M<<1],n,m,sum,s,t,S,T,cnt=1;
int pre[N],gap[N],dis[N],d[N],cur[N];
double a[N][N];
struct use{int st,en,v;
}e[M<<1];
void add(int x,int y,int v){next[++cnt]=point[x];point[x]=cnt;e[cnt].st=x;e[cnt].en=y;e[cnt].v=v;next[++cnt]=point[y];point[y]=cnt;e[cnt].st=y;e[cnt].en=x;e[cnt].v=0;
}
int isap(int ss,int tt){int mn,u=ss,i,ans(0);gap[0]=tt;for (int i=1;i<=tt;i++) gap[i]=0;for (int i=1;i<=tt;i++) dis[i]=0;for (int i=1;i<=tt;i++) cur[i]=point[i];while (dis[ss]<tt){bool f=false;for (i=cur[u];i;i=next[i]) if (e[i].v&&dis[e[i].en]+1==dis[u]){f=true;cur[u]=i;break;}if (f){pre[u=e[i].en]=i;if (u==tt){ mn=inf;for (int i=tt;i!=ss;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v);ans+=mn;for (int i=tt;i!=ss;i=e[pre[i]].st) e[pre[i]].v-=mn,e[pre[i]^1].v+=mn;u=ss;}}else{gap[dis[u]]--;if (!gap[dis[u]]) return ans;for (mn=tt,i=point[u];i;i=next[i]) if (e[i].v) mn=min(mn,dis[e[i].en]);gap[dis[u]=mn+1]++;cur[u]=point[u];if (u!=ss) u=e[pre[u]].st;}}return ans;
}
void build(){add(t,s,inf);for (int i=1;i<n;i++){if (a[i][n]!=(int)a[i][n]) add(s,i,1);d[s]-=(int)a[i][n];d[i]+=(int)a[i][n];}for (int i=1;i<n;i++){if (a[n][i]!=(int)a[n][i])add(i+n,t,1);d[t]+=(int)a[n][i];d[i+n]-=(int)a[n][i];} for (int i=1;i<n;i++)for (int j=1;j<n;j++){if (a[i][j]!=(int)a[i][j]) add(i,j+n,1);d[i]-=(int)a[i][j];d[j+n]+=(int)a[i][j];}for (int i=1;i<=t;i++)if (d[i]>0) add(S,i,d[i]),sum+=d[i];else if (d[i]<0) add(i,T,-d[i]);
}
int main(){//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);scanf("%d",&n);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%lf",&a[i][j]);s=2*n+1,t=s+1;S=t+1;T=S+1;build();if (isap(S,T)!=sum){printf("No\n");return 0;};printf("%d\n",isap(s,t)*3);
}
總結(jié)
以上是生活随笔為你收集整理的【bzoj3698】【XWW的难题】【有上下界的网络流】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。