3504 [Cqoi2014]危険な橋@ - @bzoj


@説明@

アリスとボブは、島はN-1に0の番号が付けられ、N状態の島によってシートに住んでいます。そこ両方向に橋や道路橋の間に接続されたいくつかの島がありますが、1人は合格するだけのために。危険な橋となって荒廃による橋のいくつかは、あなたは二回しか渡すことができます。アリスはにし、A1及びA2(再びアルにA2からA2に前後にアルから数える)との間に二回の島から望んでいます。一方、ボブがbl、b2の島々の間で前後億回を願っています。このプロセスは、すべての最も危険な橋の交通倍、ブリッジ無制限のアクセスの残りの部分。アリスとボブは、彼らの願いを完了するためでしょうか?

入力
この質問のテストデータの複数のセット。
各セットの最初の行は、7つのスペースは整数、それぞれ、N、ら、A2、分離含ま BL、B2、BNを。
次のN行N列、大文字の対称行列です。Iは、行と、それは「O」である場合、私は、島JL-1との間の接続を記述し、マトリクス番号のJ列は、接続された危険ブリッジがあることを示し、「N」は、接続された通常のブリッジを表すように「X」がないブリッジがないことを示すように接続されています。

出力
テストデータ出力ラインの各セットのためには、彼らは「はい」、そうでない場合は「いいえ」の出力を完了することができることを望む場合。

サンプル入力
4 0 1 1 2 3 1
XOXX
OXOX
XOXO
XXOX
4 0 2 1 3 2
XNXO
NXOX
XOXO
OXOXの
サンプル出力
はい
いいえ

レンジデータ
。4 <= N <50
O <= A1、A2、B1、B2 <-N = 1
。1 <= AN。B <= 50

@溶液@

[Bzojタイトルの顔。私は何か良いTucaoありませんよ。]

ブログの首長の詳細、偉大なディテールORZの関連する証拠を崇拝し始めて

この問題は、実際にシンク及び固定マルチソースマルチシンクの最大流量のソースとの間の一致です。
比較的簡単なアイデアを考えることができます:2に設定されたA1を接続し、スーパーソースをビルドし、B1、A2、B2、さらには超能力に沈むAN 2及び BN;容量危険な橋2に、通常のブリッジを容量はさえ双方向側として、infに設定されています。
最大流量= 2 *(+ BN)が可解である場合、このような最大流量の後、図実行を内蔵。
すべての偶数の能力のすべてのエッジが(INFが偶数として使用することができます)ので、あなたは、最大流量を決定するために2で割ったすべての能力を置くことができますので+ BNに等しい(すなわち、インターネットだけでは、1回のラウンドトリップとして見られる必要があると述べました)。

> B2とB1 - - A1なら、それは見つけることができます> A2、最大流量は必ずしも「可解」のうち、実際に解ける走りました。
別のポイント数は、<= 1を加算前後に危険な橋を制限することで、私たちはマップから構築する正方向とそれぞれ反対方向<= 1に相当します。

私たちは、最大流量の実行が再び、それが正当か否かを判断することができ、ソースs接続A1、B2、A2、B1に必要とさえトンをシンクします。
証明用として。上記述べたエッセイのブログは非常に良い話しますだから、僕は周りに固執するだろう

完全な流れであれば、次に起こる問題はまだありますか?マップを描画します。
最初のランは、最大流量は、流量のA1→B2は、フローのB1→B2はBN-Xをするために、また、B1→A2 X、A1→A2流れは、xが流れ、Xであると仮定する。
それがあるため、第2最大流量ながら実行し、A1→B2→B1およびA2の流れはBN-X、ビューまたは-Xを変更しなくてもよいです。だから、A1→B1とB2→A2フロー(注:オリジナルのブロガーをこの場所には言及した以下のコメントセクションでは、間違っている)も、やはりxはされています。
そして、A1 B1は、Xのトラフィックが流れることができるか、これらの2つのショーはまた、A1とA2、B1とB2の間のトラフィックに影響を与えることなく、B2のXの流れを流すことができます。
それは無向グラフ、逆方向流量のA1→B1のあるので、流量はB1の→B2がXで得ることができます。B1、B2は、正当な間を流れます。同様に、A1、A2は、正規の間に流れることができます。
交換B1のであれば、B2は確かに、まだ状況が存在している問題の完全な流れではありません。

二つの問題のために、前方に危険な橋後A1→A2場合、逆およびB1→B2のブリッジ、スワップB1、B2の後に、B2が出発点で、A1→A2、B2→B1二つの経路でありますこのエッジを前方にあり、それは限られたトラフィックとなっています。
まだ完全な流れのであれば、何の問題2はありません。

@acceptedコード@

#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 50;
const int MAXV = MAXN;
const int MAXE = 2*MAXV*MAXV;
const int INF = int(1E6);
struct FlowGraph{
    struct edge{
        int to, cap, flow;
        edge *nxt, *rev;
    }edges[MAXE + 5], *adj[MAXV + 5], *cur[MAXV + 5], *ecnt;
    int s, t, n;
    void clear(int _n) {
        n = _n; ecnt = &edges[0];
        for(int i=0;i<=n;i++)
            adj[i] = NULL;
    }
    void addedge(int u, int v, int c) {
        edge *p = (++ecnt), *q = (++ecnt);
        p->to = v, p->cap = c, p->flow = 0;
        p->nxt = adj[u], adj[u] = p;
        q->to = u, q->cap = 0, q->flow = 0;
        q->nxt = adj[v], adj[v] = q;
        p->rev = q, q->rev = p;
//      printf("%d %d %lld\n", u, v, c);
    }
    queue<int>que; int d[MAXV + 5];
    bool relabel() {
        for(int i=0;i<=n;i++)
            cur[i] = adj[i], d[i] = n + 5;
        while( !que.empty() ) que.pop();
        d[t] = 0, que.push(t);
        while( !que.empty() ) {
            int f = que.front(); que.pop();
            for(edge *p=adj[f];p;p=p->nxt)
                if( d[f] + 1 < d[p->to] && p->rev->cap > p->rev->flow ) {
                    d[p->to] = d[f] + 1;
                    que.push(p->to);
                    if( p->to == s ) return true;
                }
        }
        return !(d[s] == n + 5);
    }
    int aug(int x, int tot) {
        if( x == t ) return tot;
        int sum = 0;
        for(edge *&p=cur[x];p;p=p->nxt) {
            if( p->cap > p->flow && d[p->to] + 1 == d[x] ) {
                int del = aug(p->to, min(p->cap - p->flow, tot - sum));
                p->flow += del, p->rev->flow -= del, sum += del;
                if( sum == tot ) break;
            }
        }
        return sum;
    }
    int max_flow(int _s, int _t) {
        s = _s, t = _t; int flow = 0;
        while( relabel() )
            flow += aug(s, INF);
        return flow;
    }
}G;
int N, a1, a2, an, b1, b2, bn;
char str[MAXN + 5][MAXN + 5];
int main() {
    while( scanf("%d%d%d%d%d%d%d", &N, &a1, &a2, &an, &b1, &b2, &bn) == 7 ) {
        bool flag = true;
        for(int i=0;i<N;i++)
            scanf("%s", str[i]);
        G.s = N, G.t = N + 1;
        G.clear(N + 2);
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                if( str[i][j] == 'O' ) G.addedge(i, j, 1);
                else if( str[i][j] == 'N' ) G.addedge(i, j, INF);
        G.addedge(G.s, a1, an), G.addedge(G.s, b1, bn);
        G.addedge(a2, G.t, an), G.addedge(b2, G.t, bn);
        flag &= (G.max_flow(G.s, G.t) == an + bn);
        G.s = N, G.t = N + 1;
        G.clear(N + 2);
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                if( str[i][j] == 'O' ) G.addedge(i, j, 1);
                else if( str[i][j] == 'N' ) G.addedge(i, j, INF);
        G.addedge(G.s, a1, an), G.addedge(G.s, b2, bn);
        G.addedge(a2, G.t, an), G.addedge(b1, G.t, bn);
        flag &= (G.max_flow(G.s, G.t) == an + bn);
        if( flag ) puts("Yes");
        else puts("No");
    }
}

@詳細@

私は、マルチソースの複数のシンクことを聞いて、線形計画溶液で固定発生源問題のみをシンクします。それは(2ソース2つのシンク)非常に特別であるので、この質問はおそらくです。

この結論は、常に神の非常にタイトルを感じ、フィールドは、私たち単なる人間が接触することができるものではありません。
私はトップコーダーのタイトルから移動聞きました。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11416181.html