bzoj1305 跳舞

标签: NOIP bzoj 解题报告 网络流 最大流
330人阅读 评论(0) 收藏 举报
分类:
 跳舞

题目背景:

bzoj1305

分析: 我们考虑这道题,我想应该还是能够比较容易的发现这是一道网络流,不论是题面推理,还是从数据范围来看,但是要是真的有这么的简单,那就显得不太正常了······我们考虑这么一个问题,我们可以考虑如果当前最多能跳a首曲子,那么我们可以向每一个点连一条容量为a的边,然后为了方便的处理,我们

1)将每一个人拆成两个点,男孩的两个点为X1X2,女孩为Y1Y2

2)将相互喜欢的每一对的X1Y1相连,互相讨厌的将X2Y2相连

3)然后从每一个X1X2连一条容量为k的边,每一个Y2Y1连一条容量为k的边

4)从原点向每一个X1连容量a的边,从每一个Y1向汇点连容量为a的边,

然后如果我们发现最终的结果是max_flow = n * a则说明可以满足a,那么我们可以发现a是单调的,即对于一个a如果满足,那么显然的a – 1也一定能够满足那么我们就可以根据这个性质进行二分,从而判断最大的能满流的a即可。

Source

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
inline char read() {
    static const int IN_LEN = 1024 * 1024;
    static char buf[IN_LEN], *s, *t;
    if (s == t) {
        t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
        if (s == t) return -1;
    }
    return *s++;
}
 
template
inline bool R(T &x) {
    static bool iosig;
    static char c;
    for (c = read(), iosig = false; !isdigit(c); c = read()) {
        if (c == -1) return false;
        if (c == '-') iosig = true;
    } 
    for (x = 0; isdigit(c); c = read()) 
        x = (x << 3) + (x << 1) + (c ^ '0');
    if (iosig) x = -x;
    return true;
}
 
const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void writechar(char c) {
    if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
    *oh++ = c; 
}
 
template
inline void W(T x) {
    static int buf[30], cnt;
    if (!x) writechar(48);
    else {
        if (x < 0) writechar('-'), x = -x;
        for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
        while (cnt) writechar(buf[cnt--]);
    }
}
 
inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); }
 
const int MAXN = 200 + 20;
const int INF = ~0u >> 1;
int n, k, s, t;
char c;
int first[MAXN], temp[MAXN], dis[MAXN], gap[MAXN], ans[MAXN];
char map[MAXN][MAXN];
struct node {
    int to, w, f, rev;
    node(int to, int w, int rev) : f(0), to(to), w(w), rev(rev) {}
};
vector  edge[MAXN];
 
inline void create(int x, int y, int z) {
    edge[x].push_back(node(y, z, edge[y].size()));
    edge[y].push_back(node(x, 0, edge[x].size() - 1));
}
 
inline int boy1(int i) { return i;} //X1
inline int boy2(int i) { return n + i; } //X2
inline int girl1(int i) { return n * 2 + i; } //Y1
inline int girl2(int i) { return n * 3 + i; } //Y2
 
inline void readin() {
    cin >> n >> k;
    s = 0, t = 4 * n + 1;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            cin >> map[i][j];
}
 
inline void buildgraph(int mid) {
	/*每一次根据二分所得的值进行二分*/
    for (int i = s; i <= t; ++i) edge[i].clear();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j) {
            if (map[i][j] == 'Y')
                create(boy1(i), girl1(j), 1);
            else create(boy2(i), girl2(j), 1);
        }
    for (int i = 1; i <= n; ++i) {
        create(boy1(i), boy2(i), k), create(girl2(i), girl1(i), k);
        create(s, boy1(i), mid), create(girl1(i), t, mid);
    }
}
 
inline void bfs(int s, int t) {
	/*isap初始化 & bfs*/ 
    memset(dis, -1, (t + 3 << 2));
    memset(gap, 0, (t + 3 << 2));
    memset(temp, 0, (t + 3 << 2));
    queue q;
    q.push(t), dis[t] = 0, gap[0] = 1;
    while (!q.empty()) {
        int j = q.front(); q.pop();
        for (int p = 0; p < edge[j].size(); ++p) {
            node &e = edge[j][p];
            if (dis[e.to] == -1 && edge[e.to][e.rev].w > edge[e.to][e.rev].f)
                dis[e.to] = dis[j] + 1, q.push(e.to), gap[dis[e.to]]++;
        }
    }
}
 
inline int isap(int s, int t, int n) {
    static int stack[MAXN][2];
    bfs(s, t);
    int cur = s, top = 0, flow = 0;
    while (dis[s] < n) {
        if (cur == t) {
            int minn = INF, pos;
            for (int i = 0; i < top; ++i) {
                node &e = edge[stack[i][0]][stack[i][1]];
                if (minn > e.w - e.f)
                    minn = e.w - e.f, pos = i;
            }
            for (int i = 0; i < top; ++i) {
                node &e = edge[stack[i][0]][stack[i][1]];
                e.f += minn, edge[e.to][e.rev].f -= minn;
            }
            flow += minn, top = pos, cur = stack[pos][0];
            continue;
        }
        bool valid = false;
        for (int p = temp[cur]; p < edge[cur].size(); ++p) {
            node &e = edge[cur][p];
            if (dis[e.to] == dis[cur] - 1 && e.w > e.f) {
                valid = true, temp[cur] = p;
                break;
            }
        }
        if (valid) {
            stack[top][0] = cur, stack[top++][1] = temp[cur], cur = edge[cur][temp[cur]].to;
            continue;
        }
        int m = n - 1;
        for (int p = 0; p < edge[cur].size(); ++p) {
            node &e = edge[cur][p];
            if (dis[e.to] < m && e.w > e.f)
                m = dis[e.to], temp[cur] = p;
        }
        if (--gap[dis[cur]] == 0) break;
        dis[cur] = m + 1, gap[dis[cur]]++;
        if (cur != s) cur = stack[--top][0];
    }
    return flow;
}
 
inline void get() {
	/*二分获得最大值*/ 
    int l = 0, r = n + 2;
    while (l + 1 < r) {
        int mid = l + r >> 1;
        buildgraph(mid);
        if (isap(s, t, t + 1) >= mid * n) l = mid;
        else r = mid;
    }
    cout << l;
}
 
int main() {
    //freopen("dance.in", "r", stdin);
    //freopen("dance.out", "w", stdout);
    readin();
    get();
    return 0;
}

 

 

查看评论

bzoj1305: [CQOI2009]dance跳舞

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1305 思路:拆点,把每个人拆成喜欢和不喜欢,源向男生的喜欢的点连inf边,喜欢向不喜欢连K...
  • thy_asdf
  • thy_asdf
  • 2016年01月19日 08:51
  • 657

【bzoj1305】[CQOI2009]dance跳舞 最大流

Description一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“...
  • LOI_DQS
  • LOI_DQS
  • 2016年03月10日 21:12
  • 526

bzoj1305 跳舞

跳舞 题目背景: bzoj1305 分析: 我们考虑这道题,我想应该还是能够比较容易的发现这是一道网络流,不论是题面推理,还是从数据范围来看,但是要是真的有这么的简单,那就显得不...
  • scar_lyw
  • scar_lyw
  • 2017年03月06日 17:41
  • 330

BZOJ1305: [CQOI2009]dance跳舞

Description一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“...
  • HeroDeathes
  • HeroDeathes
  • 2017年11月18日 19:05
  • 369

BZOJ1305 [CQOI2009]dance跳舞

[] My 200th solved problem on BZOJ. So slow am I brus [Solution] It seems like a network flow
  • laekov
  • laekov
  • 2014年07月23日 17:41
  • 474

bzoj1305[CQOI2009]dance跳舞

最大流+二分答案,其实可以用贪心做但是……练习下网络流 #include #include #include #include #include #include #include #define L...
  • BPM136
  • BPM136
  • 2015年12月23日 17:00
  • 225

bzoj1305 [CQOI2009]dance跳舞

Description一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“...
  • lzr010506
  • lzr010506
  • 2016年04月15日 09:35
  • 236

【CQOI2009】bzoj1305 跳舞

网络流
  • sdfzyhx
  • sdfzyhx
  • 2016年11月04日 19:14
  • 206

BZOJ1305: [CQOI2009]dance跳舞

Description 一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不...
  • wxh010910
  • wxh010910
  • 2016年11月10日 21:25
  • 160

[bzoj1305][网络流]dance跳舞

Description 一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(...
  • Rose_max
  • Rose_max
  • 2017年10月01日 10:09
  • 566
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2169
    排名: 2万+
    博客专栏
    最新评论