生活随笔
收集整理的這篇文章主要介紹了
3698: XWW的难题 有源汇上下界最大流
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
有源匯上下界最大流,行列建圖,下界為ai,j,上界為ai,j+1,跑的飛起。
不要忘記判斷上取整下取整相同的情況。
using namespace std;
int n,cnt=
1,S,T,SS,TT,total,ans;
int head[N],cur[N],dis[N],
q[N],du[N];
int next[M],list[M],key[M];
double a[N>>
1][N>>
1];
int l[N>>
1][N>>
1];
inline void insert(
int x,
int y,
int z)
{
next[++cnt]=head[
x];head[
x]=cnt;list[cnt]=
y;key[cnt]=z;
}
inline bool BFS(
int S,
int T)
{
int t=
0,w=
1,
x;memset(dis,-
1,sizeof(dis));dis[S]=
1;
q[1]=S;
while (t<w){
x=
q[++t];
for (
int i=head[
x];i;i=
next[i])
if (key[i]&&dis[list[i]]==-
1)dis[
q[++w]=list[i]]=dis[
x]+
1;}
return dis[T]!=-
1;
}
int find(
int x,
int flow,
int T)
{
if (
x==T)
return flow;
int w,used=
0;
for (
int i=cur[
x];i;i=
next[i])
if (key[i]&&dis[list[i]]==dis[
x]+
1){w=find(list[i],min(flow-used,key[i]),T);key[i]-=w; key[i^
1]+=w; used+=w;
if (key[i]) cur[
x]=i;
if (used==flow)
return flow;}
if (!used) dis[
x]=-
1;
return used;
}
inline
int dinic(
int S,
int T)
{
int ans=
0;
while (BFS(S,T)){
for (
int i=
0;i<=T;i++) cur[i]=head[i];ans+=find(S,inf,T);}
return ans;
}
int main()
{scanf(
"%d",&n); n--; S=
0; T=n<<
1|
1; SS=T+
1; TT=T+
2;
for (
int i=
1;i<=n+
1;i++)
for (
int j=
1;j<=n+
1;j++)scanf(
"%lf",&a[i][j]),l[i][j]=(
int)a[i][j];
for (
int i=
1;i<=n;i++){du[i]+=l[i][n+
1],du[S]-=l[i][n+
1];
if (a[i][n+
1]!=l[i][n+
1]) insert(S,i,
1),insert(i,S,
0);}
for (
int i=
1;i<=n;i++){du[i+n]-=l[n+
1][i],du[T]+=l[n+
1][i];
if (a[n+
1][i]!=l[n+
1][i]) insert(i+n,T,
1),insert(T,i+n,
0);}
for (
int i=
1;i<=n;i++)
for (
int j=
1;j<=n;j++){du[i]-=l[i][j],du[j+n]+=l[i][j];
if (a[i][j]!=l[i][j]) insert(i,j+n,
1),insert(j+n,i,
0);}
for (
int i=
0;i<=T;i++)
if (du[i]>
0) total+=du[i],insert(SS,i,du[i]),insert(i,SS,
0);
else if (du[i]<
0) insert(i,TT,-du[i]),insert(TT,i,
0);insert(T,S,inf); insert(S,T,
0);ans=dinic(SS,TT);
if (ans!=total) puts(
"No");
else ans=dinic(S,T),
printf(
"%d\n",
3*ans);
return 0;
}
總結
以上是生活随笔為你收集整理的3698: XWW的难题 有源汇上下界最大流的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。