0411周赛

T1:NOIP2016 车站分级

思路:拓扑排序,注意建虚拟源点。

#include <bits/stdc++.h>

using namespace std;

struct node {
    int to, nxt;
}e[2000005]; int n, m, head[1000005], ind[1000005], tot, f[1000005], hi[1000005], lw[1000005], dis[1000005];
bool vis[1000005];
inline void add_e(int u, int v) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot;}

void dfs(int u)
{
    if (f[u]) return;
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        dfs(v);
        f[u] = max(f[u], f[v] + 1);
    } f[u] -= (u > n);
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
    {
        memset(vis, 0, sizeof vis);
        int t, k = 0;
        scanf("%d", &t);
        for (int j = 1, x; j <= t; j++) scanf("%d", &hi[j]), vis[hi[j]] = 1, add_e(n + i, hi[j]);
        for (int j = hi[1]; j <= hi[t]; j++) if (!vis[j]) add_e(j, n + i);
    } int ans = 0;
    for (int i = 1; i <= n; i++) if (!ind[i]) dfs(i);
    for (int i = 1; i <= n; i++) ans = max(ans, f[i]);
    printf("%d", ++ans);
}

T2:矩形操作

 思路:差分约束,把每一行和每一列当作一个点,x+y=z转化为x-(-y)=z。

#include <bits/stdc++.h>

using namespace std;

struct node {
    int to, nxt, len;
}e[2000005]; int n, m, k, head[1000005], tot, dis[1000005], cnt[1000005];
bool vis[1000005];
inline void add_e(int u, int v, int w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;}

bool spfa()
{
    queue <int> Q;
    memset(dis, 0x3f, sizeof dis);
    memset(cnt, 0, sizeof cnt);
    memset(vis, 0, sizeof vis);
    Q.push(0);
    dis[0] = 0;
    while (!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = 0;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (dis[v] > dis[u] + e[i].len)
            {
                dis[v] = dis[u] + e[i].len;
                if (++cnt[v] > 2 * n) return 0;
                if (!vis[v]) vis[v] = 1, Q.push(v);
            }
        }
    } return 1;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(head, 0, sizeof head); tot = 0;
        scanf("%d%d%d", &n, &m, &k);
        if (n <= m) swap(m, n);
        for (int i = 1, x, y, z; i <= k; i++) scanf("%d%d%d", &x, &y, &z), add_e(y + n, x, z), add_e(x, y + n, -z);
        for (int i = 1; i <= 2 * n; i++) add_e(0, i, 0);
        if (spfa()) puts("Yes");
        else puts("No");
    }
}

T3:矩阵估价

思路:讲道理这题属实yin间,居然要取log把除法转化为减法,于是又成了差分约束,建边方法和T2类似。

#include <bits/stdc++.h>

using namespace std;

struct node {
    int to, nxt;
    double len;
}e[1000000]; int n, m, x, y, vis[500005], head[500005], cnt[500005], tot, h[405][405]; double dis[500005];
inline void add_e(int u, int v, double w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;}

bool spfa()
{
    queue <int> Q;
    for (int i = 0; i <= n + m; i++) dis[i] = 1e9; 
    memset(cnt, 0, sizeof cnt);
    memset(vis, 0, sizeof vis);
    Q.push(0);
    dis[0] = 0;
    while (!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = 0;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (dis[v] > dis[u] + e[i].len)
            {
                dis[v] = dis[u] + e[i].len;
                if (++cnt[v] > n + m) return 0;
                if (!vis[v]) vis[v] = 1, Q.push(v);
            }
        }
    } return 1;
}

void solve()
{
    memset(head, 0, sizeof head); tot = 0;
    scanf("%d%d%d%d", &n, &m, &x, &y);
    for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &h[i][j]);
    double xx = log2(x), yy = log2(y);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            double hh = log2(h[i][j]);
            add_e(i, j + n, hh - xx);
            add_e(j + n, i, yy - hh);
        }
    }
    for (int i = 1; i <= n + m; i++) add_e(0, i, 0);
    if (spfa()) puts("YES");
    else puts("NO");
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--) solve();    
}

T4:海岛旅游

 

 思路:首先bfs或dfs搜出来一个个岛屿,然后最短路求两两岛屿的距离,最后状压dp解决。(讲道理这个题也很yin间)

#include <bits/stdc++.h>

using namespace std;

typedef pair <int, int> P;

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};

int pos[2505], cnt;
char ch[55][55];

int head[250005], n, m, dis[55][55], d[55][55], f[55][(1 << 15) + 1], bl[55][55];
bool vis[55][55];

bool check(int x, int y) {return x >= 1 && x <= n && y >= 1 && y <= m;}

vector <int> xx[250005];
vector <int> yy[250005]; 

void bfs(int sx, int sy)
{
    queue <P> Q;
    Q.push(make_pair(sx, sy));
    vis[sx][sy] = 1, bl[sx][sy] = cnt;
    xx[cnt].push_back(sx);
    yy[cnt].push_back(sy);
    while (!Q.empty())
    {
        int x = Q.front().first, y = Q.front().second; Q.pop();
        for (int i = 0; i < 4; i++)
        {
            int fx = x + dx[i], fy = y + dy[i];
            if (check(fx, fy) && !vis[fx][fy] && ch[fx][fy] == 'X')
            {
                Q.push(make_pair(fx, fy));
                bl[fx][fy] = cnt;
                xx[cnt].push_back(fx);
                yy[cnt].push_back(fy);
                vis[fx][fy] = 1;
            }
        }
    }
}

void spfa(int s)
{
    queue <P> Q;
    memset(vis, 0, sizeof vis);
    memset(d, 0x3f, sizeof d);
    int num = xx[s].size();
    for (int i = 0; i < num; i++)
    {
        int x = xx[s][i], y = yy[s][i];
        vis[x][y] = 1, d[x][y] = 0;
        Q.push(make_pair(x, y));
    }
    while (!Q.empty())
    {
        int x = Q.front().first, y = Q.front().second; Q.pop();
        vis[x][y] = 0; 
        for (int i = 0; i < 4; i++)
        {
            int fx = x + dx[i], fy = y + dy[i];
            if (check(fx, fy) && ch[fx][fy] != '.')
            {
                if (ch[fx][fy] == 'S')
                {
                    if (d[fx][fy] > d[x][y] + 1)
                    {
                        d[fx][fy] = d[x][y] + 1;
                        if (!vis[fx][fy])
                        {
                            vis[fx][fy] = 1;
                            Q.push(make_pair(fx, fy));
                        }
                    }
                }
                else if (ch[fx][fy] == 'X')
                {
                    if (d[fx][fy] > d[x][y])
                    {
                        d[fx][fy] = d[x][y];
                        if (!vis[fx][fy])
                        {
                            vis[fx][fy] = 1;
                            Q.push(make_pair(fx, fy));
                        }
                    }
                    dis[s][bl[fx][fy]] = dis[bl[fx][fy]][s] = min(dis[s][bl[fx][fy]], d[fx][fy]);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%s", ch[i] + 1);
    for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (!vis[i][j] && ch[i][j] == 'X') ++cnt, bfs(i, j);
    memset(dis, 0x3f, sizeof dis);
    for (int i = 1; i <= cnt; i++) dis[i][i] = 0, spfa(i);
    memset(f, 0x3f, sizeof f); int all = (1 << cnt) - 1, ans = 0x3f3f3f3f; 
    for (int i = 1; i <= cnt; i++) f[i][(1 << i - 1)] = 0;
    for (int s = 1; s <= all; s++)
    {
        for (int i = 1; i <= cnt; i++)
        {
            if (s & (1 << i - 1))
            {
                for (int j = 1; j <= cnt; j++)
                {
                    if (s & (1 << j - 1)) continue;
                    f[j][s | (1 << j - 1)] = min(f[j][s | (1 << j - 1)], dis[i][j] + f[i][s]);
                }
            }
        }
    }
    for (int i = 1; i <= cnt; i++) ans = min(ans, f[i][all]);
    printf("%d", ans);
} 

T5:最省路费

 

 思路:异或优化建图板题,可惜当时我不会。

#pragma GCC optimize(3)

#include <bits/stdc++.h>

using namespace std;

typedef pair <int, int> P;

struct node {
    int to, nxt, len;
}e[8000005]; int head[4000005], tot, dis[4000005];
bool vis[4000005];
inline void add_e(int u, int v, int w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;}

void dijkstra(int s)
{
    priority_queue <P, vector <P>, greater <P> > Q;
    memset(dis, 0x3f, sizeof dis);
    dis[s] = 0; Q.push(make_pair(0, s));
    while (!Q.empty())
    {
        int u = Q.top().second; Q.pop();
        if (vis[u]) continue; else vis[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (!vis[v] && dis[v] > dis[u] + e[i].len)
            {
                dis[v] = dis[u] + e[i].len;
                Q.push(make_pair(dis[v], v));
            }
        }
    }
}

char buf[1 << 22], *p1 = buf, *p2 = buf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)

template <class T>
inline void rd(T &a)
{
    char ch = getchar(); int x = 0, f = 1;
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    a = x * f;
}

int main()
{
    int n, m, c;
    rd(n), rd(m), rd(c);
    for (int i = 1, x, y, z; i <= m; i++)
    {
        rd(x), rd(y), rd(z);
        add_e(x, y, z);    
    } int s, t; rd(s), rd(t);
    for (int i = 0; i <= n; i++) for (int j = 1; j <= n; j <<= 1) if ((i ^ j) <= n) add_e(i, i ^ j, j * c);
    dijkstra(s); printf("%d", dis[t]);
}

 

posted @ 2021-04-13 19:51  Chasing-Dreams  阅读(72)  评论(0)    收藏  举报