P2774 方格取數問題 題解

2022-10-10 06:09:10 字數 1351 閱讀 5308

題目鏈結

這道題目解法很妙,主要用到了最大和 \(=\) 總和 \(-\) 最小捨棄和。

最小捨棄和即最小割(我們構造出乙個二分圖滿足割掉 \(=\) 捨去),我們又知最小割 \(=\) 最大流,所以是一道最大流問題。

考慮建圖:

我們發現,只要兩個點相鄰(不相容),那麼這兩個點的橫縱座標和的奇偶性一定不同,即 \((x_i+y_i)\bmod 2 \neq (x_j+y_j)\bmod 2\),所以我們可以把整個圖分成 \((x_i+y_i)\bmod 2=0\) 的點集和 \((x_i+y_i)\bmod 2=1\) 的點集。這樣就構成了二分圖。

考慮構圖:

將這兩個點集分別全部連向 \(s\) 和 \(t\)(邊權即為此方格中的數),中間相鄰點連邊(邊權為 \(inf\))。這樣我們可以保證形成最小割時,圖的中間所有邊都沒被刪,也就達成了割掉 \(=\) 捨去這一目的。最終,跑最大流即可。

#include#include#include#include#includeusing namespace std;

const int n=20000+21,inf=0x3f3f3f3f;

struct edgee[n*100];

struct node,dy[4]=;

int h[n],gap[n],flow[n],d[n];

bool vis[n];

int n,m,s,t,sum,tot=1;

inline int getnum(int x,int y)

inline bool check(int x,int y)

inline void add(int u,int v,int w);h[u]=tot;

e[++tot]=(edge);h[v]=tot;

}bool bfs()

} }return d[s]!=-1;

}void init());

}} }

}void push(int u));

}} }

}void gap(int u)

}void relabel(int u)

d[u]++;

}int hlpp()

init();

while(!q.empty()));

} }return flow[t];//最終推到匯點的就是最大流

}int main()} }

} }int ans=sum-hlpp();//我使用的是hlpp預留推進來做這個題的,沒學過的請右轉板子題p4722

printf("%d\n",ans);

return 0;

}

初學hlpp,板子不好看,請各位巨佬神犇見諒。

P2774 方格取數問題

題目描述 在乙個有 m n 個方格的棋盤中,每個方格中有乙個正整數。現要從方格中取數,使任意 2 個數所在方格沒有公共邊,且取出的數的總和最大。試設計乙個滿足要求的取數演算法。對於給定的方格棋盤,按照取數要求程式設計找出總和最大的數。輸入格式 第 1 行有 2 個正整數 m 和 n,分別表示棋盤的行...

P2774 方格取數問題

none 在乙個有 m n 個方格的棋盤中,每個方格中有乙個正整數。現要從方格中取數,使任意 2 個數所在方格沒有公共邊,且取出的數的總和最大。試設計乙個滿足要求的取數演算法。對於給定的方格棋盤,按照取數要求程式設計找出總和最大的數。輸入格式 第 1 行有 2 個正整數 m 和 n,分別表示棋盤的行...

P2774 方格取數問題

對棋盤黑白染色,源點向黑點連邊,匯點向白點連邊,權值均為這個點的權值。然後所有的黑點向白點連一條 inf 的邊。這樣求出的最小割一定會割掉與源點和匯點相連的邊,割掉這條邊相當於不選這個點。所以最後答案就是所有點的權值 最小割。include include include include defin...