題目鏈結
這道題目解法很妙,主要用到了最大和 \(=\) 總和 \(-\) 最小捨棄和。
最小捨棄和即最小割(我們構造出乙個二分圖滿足割掉 \(=\) 捨去),我們又知最小割 \(=\) 最大流,所以是一道最大流問題。
考慮建圖:
我們發現,只要兩個點相鄰(不相容),那麼這兩個點的橫縱座標和的奇偶性一定不同,即 \((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...