板题 WA 1 个点球调,玄关
查看原帖
板题 WA 1 个点球调,玄关
300098
cmaths楼主2024/1/11 15:53
#include <bits/stdc++.h>
#define ll long long

using namespace std;

int read()
{
    int x = 0, f = 1;
    char ch = 0;
    while(!isdigit(ch))
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

const int N = 1000, M = 2000, INF = 0x3f3f3f3f;

int n, m;
int s, t;

struct Gr
{
    struct Edge
    {
        int v, w, nxt;
    }edge[M + 5];
    int head[N + 5], cnte;
    void adde(int u, int v, int w)
    {
        edge[++cnte] = {v, w, head[u]};
        head[u] = cnte;
    }
}gr;

int rd[N + 5];
stack <int> st;
void hi(int u)
{
    for(int &i = rd[u]; i; )
    {
        int v = gr.edge[i].v, w = gr.edge[i].w;
        i = gr.edge[i].nxt;
        hi(v);
        st.push(w);
    }
}

struct Flo
{
    struct Edge
    {
        int v, c, nxt;
    }edge[(N + M * 3) * 2 + 5];
    int head[N + M + 5], cnte;
    void adde(int u, int v, int c)
    {
        edge[++cnte] = {v, c, head[u]};
        head[u] = cnte;
    }
    Flo()
    {
        cnte = 1;
    }
    void clr()
    {
        cnte = 1;
        for(int i = 1; i <= t; i++)
        {
            head[i] = 0;
        }
    }
}flo;

int dis[N + M + 5];
int rad[N + M + 5];
bool bfs()
{
    queue <int> qu;
    qu.push(s);
    dis[s] = 1;
    while(qu.size())
    {
        int u = qu.front();
        qu.pop();
        rad[u] = flo.head[u];
        for(int i = flo.head[u]; i; i = flo.edge[i].nxt)
        {
            int v = flo.edge[i].v;
            if(!flo.edge[i].c || dis[v])
            {
                continue;
            }
            dis[v] = dis[u] + 1;
            qu.push(v);
        }
    }
    // printf("%d\n", dis[t]);
    return (dis[t] > 0);
}
int dinic(int u, int rem)
{
    if(u == t)
    {
        return rem;
    }
    int tmp = rem;
    for(int i = rad[u]; i; i = flo.edge[i].nxt)
    {
        rad[u] = i;
        int v = flo.edge[i].v;
        if(dis[v] != dis[u] + 1 || !flo.edge[i].c)
        {
            continue;
        }
        int f = dinic(v, min(rem, flo.edge[i].c));
        rem -= f;
        flo.edge[i].c -= f;
        flo.edge[i ^ 1].c += f;
        if(!rem)
        {
            break;
        }
    }
    return tmp - rem;
}
void flowclr()
{
    for(int i = 1; i <= t; i++)
    {
        dis[i] = 0;
    }
}

struct Qu
{
    int u, v, w1, w2;
}qu[M + 5];

int deg[N + 5];
int in[N + 5], out[N + 5];
bool check(int mid)
{
    for(int i = 1; i <= m; i++)
    {
        int u = qu[i].u, v = qu[i].v, w1 = qu[i].w1, w2 = qu[i].w2;
        if(w1 > mid && w2 > mid)
        {
            return 0;
        }
        if(w1 > mid)
        {
            in[u]++, out[v]++;
        }
        else if(w2 > mid)
        {
            out[u]++, in[v]++;
        }
    }
    for(int i = 1; i <= n; i++)
    {
        if(in[i] * 2 > deg[i] || out[i] * 2 > deg[i])
        {
            return 0;
        }
    }
    int sum = 0;
    for(int i = 1; i <= n; i++)
    {
        flo.adde(i, t, deg[i] / 2 - in[i]);
        flo.adde(t, i, 0);
        sum += deg[i] / 2 - in[i];
    }
    for(int i = 1; i <= m; i++)
    {
        int u = qu[i].u, v = qu[i].v, w1 = qu[i].w1, w2 = qu[i].w2;
        if(w1 <= mid && w2 <= mid)
        {
            flo.adde(s, n + i, 1);
            flo.adde(n + i, s, 0);
            flo.adde(n + i, u, 1);
            flo.adde(u, n + i, 0);
            flo.adde(n + i, v, 1);
            flo.adde(v, n + i, 0);
        }
    }
    // printf("\n");
    int flow = 0;
    while(bfs())
    {
        flow += dinic(s, INF);
        flowclr();
    }
    // bfs();
    // dinic(s, INF);
    // printf("%d %d\n", mid, flow);
    if(flow == sum)
    {
        return 1;
    }
    return 0;
}

void checkclr()
{
    for(int i = 1; i <= n; i++)
    {
        in[i] = out[i] = 0;
    }
    flo.clr();
}

void init()
{
    n = read(), m = read();
    s = n + m + 1, t = n + m + 2;
    for(int i = 1; i <= m; i++)
    {
        int u = read(), v = read(), w1 = read(), w2 = read();
        qu[i] = {u, v, w1, w2};
        deg[u]++, deg[v]++;
    }
}

void solve()
{
    for(int i = 1; i <= n; i++)
    {
        if(deg[i] % 2)
        {
            printf("NIE");
            return;
        }
    }
    // check(500);
    int l = 1, r = 1001;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(check(mid))
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
        checkclr();
    }
    if(l == 1001)
    {
        printf("NIE");
        return;
    }
    printf("%d\n", l);
    check(l);
    for(int i = 1; i <= m; i++)
    {
        int u = qu[i].u, v = qu[i].v, w1 = qu[i].w1, w2 = qu[i].w2;
        if(w1 > l)
        {
            gr.adde(v, u, i);
        }
        else if(w2 > l)
        {
            gr.adde(u, v, i);
        }
        else
        {
            for(int j = flo.head[n + i]; j; j = flo.edge[j].nxt)
            {
                int vv = flo.edge[j].v;
                if(!flo.edge[j].c)
                {
                    gr.adde(u + v - vv, vv, i);
                }
            }
        }
    }
    for(int i = 1; i <= n; i++)
    {
        rd[i] = gr.head[i];
    }
    hi(1);
    while(st.size())
    {
        printf("%d ", st.top());
        st.pop();
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("gen.in", "r", stdin);
    freopen("my.out", "w", stdout);
#endif
    init();
    solve();
    return 0;
}

思路是题解的网络流、欧拉回路

2024/1/11 15:53
加载中...