SWUST-2019-11-10 训练赛解题报告

A - As Fast As Possible

 CodeForces - 701D

首先,明确一点,大巴车是可以回去接人的。

在这里,我们不难发现,为了达到最优解,那些还未坐车的“大部队”和坐了车的“先行部队”的距离S是固定的。


画出对应的t-x图:

我们可以列出一个方程组:


指的是总花费时间。

我们假设每个bus向前的花费时间是x,返回接学生花费时间是y,那么,最优解的情况是每一位学生都能上车一次,因为车的载客量是K,所以我们的tim是N除以K向上取整。

然后连立这两个方程就可以通过x、y之间的固定关系求解了。
 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
double L, v1, v2;
int N, K, tim;
int main()
{
    scanf("%d%lf%lf%lf%d", &N, &L, &v1, &v2, &K);
    tim = N / K + (bool)(N % K);
    double ans;
    double A = 1. * tim + 1. * (tim - 1.) * (v2 - v1) / (v2 + v1);
    double B = (v2 - v1) / A;
    ans = L / (B + v1);
    printf("%lf\n", ans);
    return 0;
}

 


B - Connecting Universities

 CodeForces - 701E

  一个树上的思维操作,跟结点的size有关哦(非一般size,是有效size)

就是给出2*K个点(一开始我竟然读成了两千个点),然后我们可以画图来看,能发现其中的某些规律。

假设如图,红色的点是题目中说到 的2*K个点。

  那么如果要去找最优解,也就是应该这样配对{5, 6}、{1, 4}也可以是{1, 6}、{5, 4}。那么,我们可以从每条边产生的贡献角度来考虑这个问题,1-2这条边要贡献一次,3-5、2-3的边也是会贡献一次,然后为了达成最优解,2-4这条边必须贡献两次,4-6也是必须贡献一次才可以。所以我们不如去看如何处理每条边的贡献。

  那么问题似乎被简化了,我们把每个结点的入度的边等效给结点上面去,(代表了3这号点的代表边是2-3),3的子树当中有一个标记点;2的子树中有3个,但是呢一共就只有4个点,所以其实1-2的边只用了4-3=1次。我们要考虑目前点的size和2*K-size的关系。
  所以,这道题简化一下,就是求树的子结点(包括本身)的有效结点个数,dfs的O(N)搜索即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, K, head[maxN], cnt, siz[maxN] = {0};
bool op[maxN] = {false};
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<1];
inline void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
ll ans = 0;
void dfs(int u, int fa)
{
    siz[u] += op[u];
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == fa) continue;
        dfs(v, u);
        siz[u] += siz[v];
    }
    ans += min(siz[u], 2 * K - siz[u]);
}
inline void init()
{
    cnt = 0;
    for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
    scanf("%d%d", &N, &K);
    init();
    for(int i=(K<<1), x; i>=1; i--)
    {
        scanf("%d", &x); op[x] = true;
    }
    for(int i=1, u, v; i<N; i++)
    {
        scanf("%d%d", &u, &v);
        _add(u, v);
    }
    dfs(1, 0);
    printf("%lld\n", ans);
    return 0;
}

 


C - Little Boxes

 HDU - 6225

  特地卡了

long long

这两个定义方式,看很多人写的是大数,但是,实际上使用

__int128

就可以解决这个问题了。(很多编译器不支持__int128)但是测评机支持。

__int128的读入,需要使用自定义读入。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
__int128 A, B, C, D, sum;
inline __int128 read()
{
    __int128 x = 0;
    char ch = getchar();
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}
inline void out(__int128 x)
{
    if(x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int main()
{
    int T; scanf("%d", &T);
    getchar();
    while(T--)
    {
        A = read(); B = read(); C = read(); D = read();
        sum = A + B + C + D;
        out(sum); puts("");
    }
    return 0;
}

 


D - Cube Stacking

 POJ - 1988

【种类并查集基础】

首先,我们来推一下样例,样例就是把1号结点放在6上面,把2号结点放在4上面,然后把4号结点放在6这个树上面,我们来看一下:

我们建立反向树,其实就是一个种类并查集的过程了。

我们一开始的时候,看向只有2、4结点的时候,是4结点权值为0,2结点权值为1(因为它下面的子树有一个结点),然后再接着合并的时候,4号结点得到了6号结点的size=2,然后2号结点被跟着更新。

(POJ对头文件的限制,会让一部分头文件变成CE)。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 3e4 + 5;
int Q, root[maxN], siz[maxN] = {0}, sum[maxN];
int fid(int x)
{
    if(x == root[x]) return x;
    int fa = root[x];
    root[x] = fid(root[x]);
    siz[x] = siz[x] + siz[fa];
    return x = root[x];
}
void Mix(int x, int y)  //把x这一列放到y这一列的上面去
{
    int u = fid(x), v = fid(y);
    if(u == v) return;
    siz[u] = sum[v];
    root[u] = v;
    sum[v] += sum[u];
}
inline void init()
{
    for(int i=1; i<maxN; i++)
    {
        root[i] = i;
        sum[i] = 1;
    }
}
int main()
{
    scanf("%d", &Q);
    init();
    char op[3]; int x, y, fa;
    while(Q--)
    {
        scanf("%s", op);
        if(op[0] == 'M')
        {
            scanf("%d%d", &x, &y);
            Mix(x, y);
        }
        else
        {
            scanf("%d", &x);
            fa = fid(x);
            printf("%d\n", siz[x]);
        }
    }
    return 0;
}

 


E - Rank of Tetris

 HDU - 1811

  我们可以首先看到题,可以先去处理相等的,也就是“=”号结点,不难发现,他们应当缩成一个点,然后我们再去建边,利用拓扑排序的性质(或者有的同学自学了Tarjan)来判断有没有环,如果有环了,说明构成了冲突,如果从任意一个0度的点出发,且仅从一个点出发,跑一次,如果所有点跑完了,就是一个确定的,如果跑出来环了,跑不下去了,那么就是说明了构成了环了,产生冲突。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=10005;
int N, M, root[maxN], head[maxN<<2], cnt, point, degree[maxN];
bool flag;
map<pair<int, int>, bool> mp;
struct eddge
{
    int no, to;
    char state;
    eddge(int a=0, int b=0, char c=NULL):no(a), to(b), state(c) {}
}ship[maxN<<1];
struct node
{
    int nex, to, val;
    node(int a=-1, int b=0, int c=0):nex(a), to(b), val(c) {}
}edge[maxN<<1];
void addEddge(int u, int v, int val)
{
    edge[cnt]=node(head[u], v, val);
    head[u]=cnt++;
}
queue<int> Q;
void init()
{
    flag=false;
    mp.clear();
    while(!Q.empty()) Q.pop();
    cnt=0;  point=N;
    memset(head, -1, sizeof(head));
    memset(degree, 0, sizeof(degree));
    for(int i=0; i<N; i++) { root[i]=i; }
}
int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); }
void mix(int x, int y)
{
    int u=fid(x), v=fid(y);
    if(u!=v)
    {
        root[u] = v;
        point--;
    }
}
void bfs()
{
    while(!Q.empty())
    {
        if(Q.size()>1) flag=true;
        int now=Q.front();  Q.pop();
        for(int u=head[now]; u!=-1; u=edge[u].nex)
        {
            int v=edge[u].to;
            degree[v]--;
            if(degree[v]==0)
            {
                Q.push(v);
                point--;
            }
        }
    }
}
int main()
{
    while(scanf("%d%d", &N, &M)!=EOF)
    {
        init();
        for(int i=1; i<=M; i++)
        {
            scanf("%d %c %d", &ship[i].no, &ship[i].state, &ship[i].to);
            if(ship[i].state == '=')
            {
                mix(ship[i].no, ship[i].to);
            }
        }
        for(int i=1; i<=M; i++)
        {
            if(ship[i].state == '=') continue;
            if(ship[i].state == '<')
            {
                if(mp[make_pair(fid(ship[i].to), fid(ship[i].no))]) continue;
                mp[make_pair(fid(ship[i].to), fid(ship[i].no))]=true;
                addEddge(fid(ship[i].to), fid(ship[i].no), 1);
                degree[fid(ship[i].no)]++;
            }
            else
            {
                if(mp[make_pair(fid(ship[i].no), fid(ship[i].to))]) continue;
                mp[make_pair(fid(ship[i].no), fid(ship[i].to))]=true;
                addEddge(fid(ship[i].no), fid(ship[i].to), 1);
                degree[fid(ship[i].to)]++;
            }
        }
        for(int i=0; i<N; i++)
        {
            if(degree[fid(i)]==0 && root[i]==i)
            {
                Q.push(fid(i));
                point--;
            }
        }
        bfs();
        if(point>0) printf("CONFLICT\n");
        else if(flag) printf("UNCERTAIN\n");
        else printf("OK\n");
    }
    return 0;
}


F - Mike and Shortcuts

 CodeForces - 689B

题意:有N个十字路口,我们是从十字路口1号出发,问到1~N这几号十字路口的最短举例,然后,对于每个十字路口,都有一个近路可以走,路径长度都是1,并且是单向边。最后输出从1出发到1~N这些点的最短举例。

我们可以直接建边,但是别忘了考虑,我们可以从i点回到i-1这个点的可能性,因为有可能回溯回来再走是更优的解。

所以,我们的做法就是去跑一个线形dp最短路即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, a[maxN], dp[maxN], head[maxN], cnt;
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<2];
inline void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
void tp()
{
    queue<int> Q;
    Q.push(1); dp[1] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i=head[u], v; ~i; i=edge[i].nex)
        {
            v = edge[i].to;
            if(dp[v] > dp[u] + 1)
            {
                dp[v] = dp[u] + 1;
                Q.push(v);
            }
        }
    }
}
int main()
{
    scanf("%d", &N);
    for(int i=1; i<=N; i++) head[i] = -1;
    for(int i=1; i<=N; i++)
    {
        scanf("%d", &a[i]);
        addEddge(i, a[i]);
        if(i < N) addEddge(i, i + 1);
        if(i > 1) addEddge(i, i-1);
    }
    memset(dp, INF, sizeof(dp));
    tp();
    for(int i=1; i<=N; i++) printf("%d ", dp[i]);
    puts("");
    return 0;
}

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值