Codeforces Round #212 (Div. 2) 不徹底不正確題解

比賽地址:http://codeforces.com/contest/362python

參考連接:http://codeforces.com/blog/entry/9584#comment-150925ios

A. Two Semiknights Meet

我不喜歡CF的題的一個緣由是它的題意太"複雜「,並且有"反人類"傾向。(笑數組

本題中就有一個表述:ide

After the meeting the semiknights can move on, so it is possible that they meet again.函數

初看此題的人可能會忽略這個細節,可是這個此題巧妙解法的一個關鍵編碼

先說通常解法spa

  1. 分別用BFS(or DFS)求出騎士A和騎士B所能到達的位置以及到達位置時的時間。code

  2. 若是A和B都能到達maze[i][j] != ‘#’,且時間爲Ta和Tb。blog

  3. 若是(Ta - Tb) % 2 == 0時,則能夠達成meeting條件,反之不能夠。(若是一個騎士先到達位置,則能夠重複來回跳從而湊足步數。)排序

再說巧妙解法:

  1. 由於移動規則的限制,每一輪兩個騎士的相對位置只會有以下幾種狀況:x + 4 or x - 4 or y + 4 or y - 4 or 不變

  2. 因此若是(A.x - B.x) % 4 == 0 || (A.y - B.y) % 4 == 0,則能夠肯定A和B能夠到達同一點,但這一點能夠不爲'#'。

  3. 若是A和B到達了某一個'#'點,根據上面的條件(meet again),則咱們能夠反推A或B到達該點的路徑,到達A或B的出生點,從而知足條件。

B. Petya and Staircases

簡單題。只須要查找有沒有i, i+1, i+2均爲dirty stairs的就能夠了。

坑點:

  1. m可能爲0
  2. 木有了

C. Insertion Sort

題意很扭曲。簡單表示就是,給你一個序列,讓你作插入排序。排序前給你一個機會讓你交換兩個數的位置,使插入排序使用swap函數的次數最少。請問有幾種交換方法,此時使用swap函數的次數是多少。

易得,插入排序使用swap的次數等於序列的逆序數。因此咱們交換的目的是減小逆序數。

咱們枚舉pair(A[i], A[j]),且i < j。此時對於逆序數的變化值爲 (A[i+1 ... j-1]中小於j的數的個數) + (A[i+1 ... j-1]中大於i的個數)

這個統計可使用樹狀數組來解決。不詳細說了。(樹狀數組 - Wiki)

D. Fools and Foolproof Roads

又是一道題意抽風題。大概題意就是一個國家,分紅n個區域,區域之間不聯通(也不電信^_^)。如今想用p條路鏈接區域,將這n個區域連爲q個區域。鏈接兩個區域的代價是: min(10^9, S + 1)。S是鏈接的兩個區域中的路徑長度之和。

坑:

  1. int可能會溢出,不過不影響最後結果。

  2. min(10^9, S + 1)中的 +1

  3. 若是A~B已經有一條路徑,咱們還能夠新建A~B的路徑,且花費爲1000。(用來湊足路徑數的關鍵。這個條件太扭曲了!怒吐一槽!)

若是簡化題意和坑,這題就是一個比較簡單的Huffman編碼的變種。可是加上這些坑和限制,就有的折騰了。

E. Petya and Pipes

一個明顯的最小費用流。小小的處理一下費用上界就能夠了。


下面是各類代碼

A. Two Semiknights Meet

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const size_t N = 8;

struct Point {
    int x,y;
    Point(){}
    Point(int ix, int iy): x(ix), y(iy){}
};

char maze[N+5][N+5];

int main()
{
    freopen("input.txt", "r", stdin);
    int T;
    input(T);
    while (T--) {
        for (int i = 0; i < (int)N; i++) {
            scanf("%s", maze[i]);
        }
        int p = 0;
        Point ks[2];
        for (int i = 0; i < (int)N; i++) {
            for (int j = 0; j < (int)N; j++) {
                if (maze[i][j] == 'K') {
                    ks[p++] = Point(i, j);
                }
            }
        }
        int dy = ks[0].y - ks[1].y;
        int dx = ks[0].x - ks[1].x;

        puts(dy % 4 == 0 && dx % 4 == 0? "YES" : "NO");
    }
    return 0;
}

B. Petya and Staircases

(n, m) = map(int, raw_input().split())
if m:
    dirties = sorted(map(int, raw_input().split()))

if not m:
    print 'YES'
elif (dirties[0] == 1 or dirties[-1] == n):
    print 'NO'
else:
    for i in xrange(m):
        p = dirties[i:i+3]
        if (len(p) != 3):
            continue
        else:
            if p[0] == p[1] - 1 == p[2] - 2:
                print 'NO'
                break
    else:
        print 'YES'

C. Insertion Sort

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const int SIZE = 5120;
const int INF = 0x3f3f3f3f;

inline int lowbit(int x)
{
    return x&(-x);
}

struct BIT//點更新,區間查詢
{
    int baum[SIZE];
    inline void init()
    {
        memset(baum,0,sizeof(baum));
    }
    void add(int x,int val)
    {
        while(x<SIZE)
        {
            baum[x]+=val;
            x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int res=0;
        while(x>0)
        {
            res+=baum[x];
            x-=lowbit(x);
        }
        return res;
    }
    int sum(int a,int b)//查詢區間和
    {
        return sum(b)-sum(a-1);
    }
};

int n;
int A[SIZE];

int main()
{
    freopen("input.txt", "r", stdin);
    BIT bit;
    input(n);
    for (int i = 0; i < n; i++) {
        input(A[i]);
        A[i]++;
    }
    int ans = -INF;
    int ans_cnt = -1;
    for (int i = 0; i < n; i++) {
        bit.init();
        bit.add(A[i], 1);
        for (int j = i + 1; j < n; j++) {
            int adv = 0;
            bit.add(A[j], 1);
            adv -= bit.sum(0, A[j] - 1);
            adv += bit.sum(A[j] + 1, n);

            adv += bit.sum(0, A[i] - 1);
            adv -= bit.sum(A[i] + 1, n);

            if (adv == ans) {
                ans_cnt++;
            } else if (adv > ans) {
                ans = adv;
                ans_cnt = 1;
            }
        }
    }
    int inv = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (A[j] > A[i]) {
                inv++;
            }
        }
    }
    print(inv - ans + 1<< ' ' << ans_cnt);
    return 0;
}

D. Fools and Foolproof Roads

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <queue>
#include <map>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

typedef long long llint;

const int SIZE = 100100;
const llint INF = 1000000000LL;

struct Road {
    int from, to;
    llint cost;
    Road(){}
    Road(int ifrom, int ito, llint icost): \
            from(ifrom), to(ito), cost(icost) {}
};

struct Distinct {
    int nr;
    llint tot;
    Distinct(){}
    Distinct(int inr, llint itot): \
            nr(inr), tot(itot){}

    friend bool operator < (const Distinct& a, const Distinct& b)
    {
        return a.tot > b.tot;
    }
};

int n, m, p ,q;
vector<Road> road_vec, new_road_vec;
int cnc[SIZE];
llint rlen[SIZE];

void init()
{
    road_vec.clear();
    new_road_vec.clear();
    for (int i = 0; i < SIZE; i++) {
        cnc[i] = i;
    }
    memset(rlen, 0, sizeof(rlen));
}

int get_father(int x)
{
    if (cnc[x] == x) return x;
    else return cnc[x] = get_father(cnc[x]);
}

int make_union()
{
    for (int i = 0;i < (int)road_vec.size(); i++) {
        int from = road_vec[i].from;
        int to = road_vec[i].to;
        cnc[get_father(from)] = cnc[get_father(to)];
    }
    set<int> st;
    for (int i = 0; i < n; i++) {
        st.insert(get_father(cnc[i]));
    }
    return st.size();
}

void fill_rlen()
{
    for (int i = 0; i < (int)road_vec.size(); i++) {
        int from = road_vec[i].from;
        int cost = road_vec[i].cost;
        rlen[get_father(from)] += cost;
    }
}

llint solve()
{
    llint res = 0;
    priority_queue<Distinct> pq;
    for (int i = 0; i < n; i++) {
        if (get_father(i) != i) continue;
        else {
            pq.push(Distinct(i, rlen[i]));
        }
    }
    for (int i = 0; i < p && pq.size() >= 2; i++) {
        Distinct a = pq.top();
        pq.pop();
        Distinct b = pq.top();
        pq.pop();
        llint cost = min(INF, a.tot + b.tot + 1);
        res += cost;
        new_road_vec.push_back(Road(a.nr, b.nr, -1));
        Distinct c(a.nr, a.tot + b.tot + cost);
        pq.push(c);
    }
    return res;
}

int main()
{
    freopen("input.txt", "r", stdin);
    int a, b;
    llint c;
    while(input(n >> m >> p >> q)) {
        init();
        while (m--) {
            input(a >> b >> c);
            a--;b--;
            road_vec.push_back(Road(a, b, c));
        }
        int us = make_union();
        fill_rlen();
        if (us - p > q || us < q) {
            print("NO");
            continue;
        } 
        llint ans = 0;
        int t = 0;
        bool need_fill = false;
        Road road_fill;
        if (us - p < q) {
            t = p - (us - q); 
            p = us - q;
            need_fill = true;
        }
        ans += solve();
        if (need_fill && \
                road_vec.empty() &&
                new_road_vec.empty()) {
            print("NO");
            continue;
        } else if (need_fill) {
            road_fill = !road_vec.empty()? road_vec[0]: new_road_vec[0];
        }
        print("YES");

        for (int i = 0; i < t; i++) {
            new_road_vec.push_back(road_fill);
        }
        ans += 1000 * t;
        for (int i = 0; i < (int)new_road_vec.size(); i++) {
            printf("%d %d\n", 
                    new_road_vec[i].from + 1, 
                    new_road_vec[i].to + 1);
        }
        //print(ans);
    }
    return 0;
}

E. Petya and Pipes

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const int NODE = 1024;
const int EDGE = 180000;
const int INF  = 0x3f3f3f3f;

struct edge
{
    int dest, flow, cost, next;
    edge(){}
    edge(int idest, int iflow, int icost, int inext): \
            dest(idest), 
            flow(iflow), 
            cost(icost), 
            next(inext){}
};

edge g[EDGE];
int ind;
int head[NODE],pre[NODE];
int dis[NODE];
char visit[NODE];
int n, K;


inline void _addEdge(int st,int end,int flow,int cost)
{
    g[ind]=edge(end,flow,cost,head[st]);
    head[st]=ind++;
}

inline void addEdge(int st,int end,int flow,int cost)
{
    _addEdge(st,end,flow,cost);
    _addEdge(end,st,0,-cost);
}

void init()
{
    memset(head,-1,sizeof(head));
    ind=0;
}

int spfa(int source,int sink)
{
    queue<int> q;
    memset(dis,0x3f,sizeof(dis));
    memset(visit,0,sizeof(visit));
    pre[source]=-1;
    q.push(source);
    visit[source]=1;
    dis[source]=0;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        visit[now]=0;
        for(int i=head[now];i!=-1;i=g[i].next)
        {
            int next=g[i].dest;
            int cost=g[i].cost;
            int flow=g[i].flow;

            if(flow>0 && dis[next]>dis[now]+cost)
            {
                dis[next]=dis[now]+cost;
                if(!visit[next])
                {
                    q.push(next);
                    visit[next]=1;
                }
                pre[next]=i;
            }
        }
    }
    return dis[sink];
}

void MinCostMaxFlow(int source, int sink, int &maxflow, int &mincost)
{
    int flow;
    maxflow = 0; mincost = 0;
    while(1)
    {
        int cost = spfa(source, sink);
        if(cost >= INF) break;
        flow = INF;
        int now = sink;
        while(now != source)
        {
            flow = min(flow, g[pre[now]].flow);
            now = g[pre[now] ^ 1].dest;
        }

        if (mincost + flow * cost > K) {
            maxflow += (K - mincost) / cost;
            break;
        }
        maxflow += flow;
        mincost += flow * cost;
        now     =  sink;
        while(now != source)
        {
            g[pre[now]].flow     -= flow;
            g[pre[now] ^ 1].flow += flow;
            now = g[pre[now] ^ 1].dest;
        }
    }
}

int main()
{
    freopen("input.txt","r", stdin);
    int a;
    input(n >> K);
    init();
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            input(a);
            if (a) {
                addEdge(i, j, a, 0);
                addEdge(i, j, K, 1);
            }
        }
    }
    int flow, cost;
    MinCostMaxFlow(1, n, flow, cost);
    print(flow);
    return 0;
}
相關文章
相關標籤/搜索