ディレクトリ
@説明@
(RI、CI)に市松のH * W上のNカード、I AI値カードの重量。複数のカード位置に配置することができます。
あなたは、各行に1枚のカードの最大値をピックアップし、各列に一枚のカードの最大を拾うことができます。
右のカードを検索し、最大値を拾います。
制約は、
すべての値は整数です。
^ 51≤N≤10、1≤H、W≤10^ 5、1≤Ai≤10^ 5、1≤Ri≤H、1≤Ci≤W。
入力
:以下のフォームの形で
NHW
C1 A1のR1
R2 C2 A2
⋮
⋮
RN AN CN
出力
可能な出力電力と最大。
サンプル入力
6 2 2
2 2 2
1 1 8
1 5
1 2 9
1 2 7
2 1 4
サンプル出力
28
試料は次のように説明した
第一行から第四のカードA4を拾います。
A6は、第二行からカードを拾います。
A2は、第三列目から2枚目のカードを拾いました。
A5は、4行目から5枚目のカードを拾いました。
そして最終重量= A4 + A6 + A2 + A5 = 9 + 7 + 4 + 8 = 28。
@溶液@
この質問は、それがネットワークフローでなければならないことを知ってください。
我々は、各カードに接続されたソース、コスト、重量1の容量であり、カードが行と列に接続され、0のコストの容量、行ごとに、シンク側に接続され、1の容量、コストはゼロです。
このマップの建物は答えである最大コストの流れを使い果たしました。
この観察は、それが常に増大ししようとするパスに沿って最大のカードの重みを考えることが最初であり、その増強手順は、いくつかの時点でextemdedませんカードを通じて以前(撤回拡張されていないことがわかり、マップを構築しました。 )削除されます。
そう:我々は、カードあたりの重量によってカードは前のカードと共存できるかどうかを判断するために、それぞれの添加を降順を追加することを検討することができます。
図は完璧にマッチ残っている場合我々は、実際に二部グラフの外に構築されている図は、我々は、カードの各添加後定理判定ホールを使用することができます考えます。
- | | <| S | T =隣人のサイズは、Tを設定し、書き込むことができます>ドットサイズのセットS:ホール定理の内容があることを思い出し = 0。ここでの私たちの隣人はポイントセットを設定し、それらが置かれているランクのセットを表します。
我々は状況が満たさホールの定理ではありません探してみてください。
唯一の単一のポイントがある場合は、| T | - | S | = 1。あなたが同じ行またはそれと同じ列にないポイントを追加した場合場合、| T | - | S |が大きくなり、我々の目的に反し、かつそれが同じ行または列にポイントを追加| T | - |変わらないが、ポイントを追加した後に作成する可能性が高いです| | T | S - | S |が小さくなるので、より多くの可能性が高い。この点に参加するにはホール定理を満たしていません。
だから、:私たちは常に同じ列の同じ行のすべてのポイントのポイントセットを探すことにより、点の集合を拡大しているが、この時点で展開していないときに決定| T | - | S |ホール定理を満たしています。
(| T |すなわち上記の)私たちは互いに素セットの行と列の上に構築し、そしてコレクションはどのように多くの列の行数が含まれていますランク内で設定統計情報を確認することができます実現に固有のこれらのカード(すなわち上記のどのくらいのランクに| S |)。
カードが追加されるたびに、それを維持すると同時に、収集と調査により収集のランクにそれを置くとします。もちろん、参加する前に合法性を判断する(すなわち、完全にはこのカードに参加するかどうか、それはのコレクションに表示されます| T | - | S | < 0)。
@acceptedコード@
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100000;
struct node{
int R, C, A;
friend bool operator < (node a, node b) {
return a.A < b.A;
}
}nd[MAXN + 5];
int fa[2*MAXN + 5], key[2*MAXN + 5], siz[2*MAXN + 5];
int find(int x) {
return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
int N, H, W;
int main() {
long long ans = 0;
scanf("%d%d%d", &N, &H, &W);
for(int i=1;i<=H;i++) fa[i] = i, siz[i] = 1, key[i] = 0;
for(int i=1;i<=W;i++) fa[i + H] = i + H, siz[i + H] = 1, key[i + H] = 0;
for(int i=1;i<=N;i++)
scanf("%d%d%d", &nd[i].R, &nd[i].C, &nd[i].A);
sort(nd + 1, nd + N + 1);
for(int i=N;i>=1;i--) {
int fx = find(nd[i].R), fy = find(nd[i].C + H);
if( fx == fy ) {
if( siz[fx] >= key[fx] + 1 ) {
key[fx]++;
ans += nd[i].A;
}
}
else {
if( siz[fx] + siz[fy] >= key[fx] + key[fy] + 1 ) {
siz[fx] += siz[fy], key[fx] += key[fy] + 1, fa[fy] = fx;
ans += nd[i].A;
}
}
}
printf("%lld\n", ans);
}
@詳細@
先生は何とかこの奇妙なゲームをプレイするために引き出します。。。
私の心の中で、質問は今、ホールの定理はまだダウンダウン、それが少ないと考えられています。