[editorial] 오늘의 하드 풀기: SRM367 D1 Hard WSNParentsAssignment

  • JongMan
    JongMan

    오늘의 문제는 SRM367 Hard 입니다. ^^
    [문제 보러 가기]
    자아 열심히 풉시다! ^ㅁ^

    [이 글은 과거 홈페이지에서 이전된 글입니다. 원문보기]

    17년 전
4개의 댓글이 있습니다.
  • JongMan
    JongMan

    SRM367 연습라운드를 5시에 아레나에 모여서 하기로 했다네요. SRM367 안하신분들 시간되면 그때 아레나에서 보아요~ :D


    17년 전 link
  • JongMan
    JongMan

    4시인데 5시로 착각함.. -_-;


    17년 전 link
  • JongMan
    JongMan

    음 푼사람 나밖에 없나;; 일루옹 미워여 OTL
    Network flow 를 이용해 특정 burden level 이 가능한가 불가능한가를 알 수 있습니다. 그럼 가능한 최소의
    burden level 을 찾은 후,맨 앞사람부터 각 사람의 parent 를 고정시켜 가면서 이 경우에도 valid
    assignment 가 있는지를 확인하면서 답을 만들어나가면 됩니다.
    이런 문제는 답 만드는 과정이 어렵고요.. 실제로 특정 burden level 이 가능한가 여부는.. 이분매칭하듯이 이분그래프를
    만들고, sink 들에서 supersink 로 연결되는 간선 capacity 를 burden level 로 두고, (a,b)
    간선을 해당 소스에서 싱크로 연결하고, 각 소스에서 슈퍼싱크로 연결해서 확인하면 됩니다. 음 그림이 없으니 힘드네요. 한번
    그려보세요 ㅋ
    [spoiler="소스코드 보기"]~~~ cpp
    #line 2 "WSNParentsAssignment.cpp"
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
    #define FOR(i,a,b) for(int i = (a); i < (b); ++i)
    #define REP(i,n) FOR(i,0,n)
    #define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
    #define pb push_back
    #define all(x) (x).begin(),(x).end()
    #define CLEAR(x,with) memset(x,with,sizeof(x))
    #define sz size()
    typedef long long ll;
    const int MAXV = 200;
    struct NetworkFlow
    {
    int flow[MAXV][MAXV], cap[MAXV][MAXV], totalFlow, V;
    NetworkFlow(int V = 0): V(V) { CLEAR(cap,0); CLEAR(flow,0); totalFlow = 0; }
    void clear() { CLEAR(cap,0); CLEAR(flow,0); totalFlow = 0; }
    void addEdge(int a, int b, int c) { cap[a][b] += c; }
    void push(int a, int b, int c) { flow[a][b] += c; flow[b][a] = - flow[a][b]; }
    int res(int a, int b) { return cap[a][b] - flow[a][b]; }
    int pushFlow(int source = 0, int sink = 1)
    {
    vector pred(V, -1); queue q;
    q.push(source); pred[source] = source;
    while(!q.empty() && pred[sink] == -1)
    {
    int u = q.front(); q.pop();
    for(int v = 0; v < V; ++v) if(res(u,v) > 0 && pred[v] == -1) { pred[v] = u; q.push(v); }
    }
    if(pred[sink] == -1) return 0;
    int h, amt = 987654321;
    h = sink; while(pred[h] != h) { amt <?= res(pred[h], h); h = pred[h]; }
    h = sink; while(pred[h] != h) { push(pred[h], h, amt); h = pred[h]; }
    totalFlow += amt;
    return amt;
    }
    };
    struct WSNParentsAssignment
    {
    int n;
    vector adj[51];
    string nearest;
    vector fixed;
    NetworkFlow net;
    bool tryMatch(int burden)
    {
    net.clear();
    int SRC = n*3;
    int SNK = n*3+1;
    REP(i,n) net.addEdge(SRC, i*2, 1);
    REP(i,n) net.addEdge(i*2+1, SNK, burden);
    REP(here,n) REP(i,adj[here].sz)
    {
    if(fixed[here] != -1 && fixed[here] != i) continue;
    int there = adj[here][i];
    int vertex = (there == n ? SNK : there * 2 + 1);
    net.addEdge(here*2, vertex, 1);
    }
    while(net.pushFlow(SRC, SNK));
    return net.totalFlow >= n;
    }
    vector minNetworkBurdenLevel(vector network, string nearest)
    {
    n = network.sz;
    vector c = network;
    REP(k,c.sz) REP(i,c.sz) REP(j,c.sz) if(c[i][k] == 'Y' && c[k][j] == 'Y') c[i][j] = 'Y';
    REP(i,c.sz)
    {
    bool seen = nearest[i] == 'Y';
    REP(j,c.sz) if(c[i][j] == 'Y' && nearest[j] == 'Y') { seen = true; }
    if(!seen) return vector();
    }
    net = NetworkFlow(n*3 + 2);
    REP(i,n)
    {
    REP(j,n)
    if(network[i][j] == 'Y')
    adj[i].pb(j);
    if(nearest[i] == 'Y') adj[i].pb(n);
    }
    fixed.resize(n, -1);
    int lo = 0, hi = n+1;
    while(lo+1 < hi)
    {
    int mid = (lo+hi)/2;
    if(tryMatch(mid))
    hi = mid;
    else
    lo = mid;
    }
    if(hi == n+1) return vector();
    printf("resulting burden %d\n", hi);
    vector ret(n);
    REP(i,n)
    {
    REP(j,adj[i].sz)
    {
    fixed[i] = j;
    ret[i] = adj[i][j];
    if(tryMatch(hi))
    break;
    }
    }
    return ret;
    }
    };
    // Powered by FileEdit

    # 지정된 언어 [/spoiler]를 찾을 수 없습니다.

    17년 전 link
  • legend12
    legend12

    이분매칭하듯이 max-flow 를 이용해서 최소의 burden level 을 구하는데까지는 성공했는데, 문제는 그 다음에 lex-smallest 인 매칭을 구하지 못해서 못풀었음 OTL
    뭔가 깔삼한 방밥이 따로있는듯 ㅠㅠ


    17년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.