bzoj3661

网络流/贪心

网络流做法是对于每一列,如果一个兔子下一天继续可以存在,那么连一条容量为1的边,然后设立一个中转站,来控制可以换的数量,容量限制l。时限100s,能跑过去我的太慢了,一个点100s

正解是贪心。不会证明。每一只兔子,我们当然希望能够尽量连续多跑几天,给其他兔子留机会。每次把在的兔子和不在的兔子排序,具体程序,然后看前l个能不能交换。

巨慢无比的网络流

#include<bits/stdc++.h>
using namespace std;
const int N = 805 * 805, inf = 1 << 29;
struct edge {
    int nxt, to, f;
} e[N * 40];
int n, m, k, l, S1, T, S, cnt = 1;
int q[N * 3 + 1621], d[N * 3 + 1621], head[N * 3 + 1621], iter[N * 3 + 1621];
int a[810][810], b[810][810];
#define id(i, j) (i - 1) * m + j
inline void link(int u, int v, int f)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v;
    e[cnt].f = f;
}
inline void ins(int u, int v, int f)
{
    link(u, v, f); 
    link(v, u, 0);
}
bool bfs()
{
    int l = 1, r = 0;
    q[++r] = 0;
    memset(d, 0, sizeof(d));
    d[0] = 1;
    while(l <= r)
    {
        int u = q[l++];
        for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && !d[e[i].to])
        {
            d[e[i].to] = d[u] + 1;
            if(e[i].to == T) return 1; 
            q[++r] = e[i].to;
        }
    }
    return 0;
}
int dfs(int u, int delta)
{
    if(u == T) 
        return delta;
    int ret = 0;
    for(int &i = iter[u]; i && delta; i = e[i].nxt) if(e[i].f && d[e[i].to] == d[u] + 1)
    {
        int x = dfs(e[i].to, min(delta, e[i].f));
        e[i].f -= x; 
        e[i ^ 1].f += x;
        ret += x;
        delta -= x; 
    }
    d[u] = 0;
    return ret;
}
inline int dinic()
{
    int ret = 0;
    while(bfs())
    {
        for(int i = 0; i <= T; ++i)
            iter[i] = head[i];
        ret += dfs(0, inf);
    }
    return ret;
}
void build()
{
    T = n * m + N * 2 + m * 2 + 2;
    S1 = n * m + N * 2 + m * 2 + 1;
    ins(0, S1, k);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) if(a[i][j])
        {
            ins(id(i, j), id(i, j) + N, 1);
            b[i][j] = cnt - 1;
        }
    for(int i = 1; i <= n; ++i)
    {
        if(a[i][1])
            ins(S1, id(i, 1), 1);
        if(a[i][m])
            ins(id(i, m) + N, T, 1);
    }
    for(int j = 2; j <= m; ++j)
        ins(n * m + N * 2 + j, n * m + N * 2 + j + m, l);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) if(a[i][j])
        {
            if(j < m)
                if(a[i][j + 1])
                    ins(id(i, j) + N, id(i, j + 1), 1);
            if(j < m)
                ins(id(i, j) + N, n * m + N * 2 + j + 1, 1);
            if(j > 1)
                ins(n * m + N * 2 + j + m, id(i, j), 1);
        }
}
int main()
{
//  freopen("input.txt", "r", stdin);
    scanf("%d%d%d%d", &n, &m, &k, &l);
    for(int i = 1; i <= n; ++i)
    {
        char s[810]; scanf("%s", s + 1);
        for(int j = 1; j <= m; ++j)
            a[i][j] = s[j] - '0';
    }
    build();
    int ans = dinic();
    if(ans < k)
    {
        puts("-1");
        return 0;
    }
    for(int j = 1; j <= m; ++j)
    {
        for(int i = 1; i <= n; ++i)
            if(b[i][j])
                if(e[b[i][j]].f == 0)
                    printf("%d ", i);
        puts("");
    }
//    fclose(stdin);
    return 0;
}
View Code

贪心

#include<bits/stdc++.h>
using namespace std;
const int N = 810 * 810, inf = 1 << 29;
int n, m, k, l;
typedef pair<int, int> PII;
int pos[810][810], a[810][810], mark[810];
PII b[810][810], c[810][810]; 
bool cp1(PII x, PII y)
{
    return x.first < y.first;
}
bool cp2(PII x, PII y)
{
    return x.first > y.first;
}
int main()
{
    scanf("%d%d%d%d", &n, &m, &k, &l);
    for(int i = 1; i <= n; ++i)
    {
        char s[810]; scanf("%s", s + 1);
        for(int j = 1; j <= m; ++j)
            a[i][j] = s[j] - '0';
    }
    for(int j = 1; j <= m; ++j)
        for(int i = 1; i <= n; ++i) if(a[i][j])
        {
            int Pos = j;
            b[j][i] = c[j][i] = make_pair(1, i);
            while(a[i][Pos + 1])
            {
                ++Pos;
                ++b[j][i].first;
                ++c[j][i].first;
            }
        }
    sort(b[1] + 1, b[1] + n + 1, cp2);
    for(int i = 1; i <= k; ++i)
        if(b[1][i].first > 0) 
            pos[1][++pos[1][0]] = b[1][i].second;
    if(pos[1][0] < k)
    {
        puts("-1");
        return 0;
    } 
    sort(pos[1] + 1, pos[1] + k + 1);
    for(int i = 1; i <= k; ++i)
        printf("%d ", pos[1][i]);
    puts("");
    for(int j = 2; j <= m; ++j)
    {
        memset(mark, 0, sizeof(mark));
        for(int i = 1; i <= k; ++i)
            mark[pos[j - 1][i]] = 1;
        for(int i = 1; i <= n; ++i)
            if(mark[i])
                c[j][i].first = -1;
            else
                b[j][i].first = inf;  
        sort(b[j] + 1, b[j] + n + 1, cp1);
        sort(c[j] + 1, c[j] + n + 1, cp2);
        for(int i = 1; i <= l; ++i)
            if(b[j][i].first < c[j][i].first)
                pos[j][i] = c[j][i].second;
            else
                pos[j][i] = b[j][i].second;
        for(int i = l + 1; i <= k; ++i)
            pos[j][i] = b[j][i].second;
        sort(pos[j] + 1, pos[j] + k + 1);
        for(int i = 1; i <= k; ++i)
            printf("%d ", pos[j][i]);
        puts("");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7066126.html