20170117 机房『练习赛』

20170117 机房『练习赛』

现代科学,面广枝繁,不是一辈子学得了的。惟一的办法是集中精力,先打破一缺口,建立一块或几块根据地,然后乘胜追击,逐步扩大研究领域。此法单刀直入,易见成效。
—— 王梓坤

我热爱生活,我是一名快速成长的OIer

目录:

T1 COLOR

#include <cstdio>
#include <algorithm>
#include <cstring>
#define PROGRAM_NAME "color"
using namespace std;
template<class TE>inline void readin(TE &res)
{
    char ch;
    while ((ch=getchar())<'0'||ch>'9');
    res=ch-'0';
    while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-'0';    
}
const int MAXN = 100000+10000;
const int MAXM = 250000*2+10000;
const int MAXT = 100000+10000;
struct Edge
{
    int v, next;
}t[MAXM];
int T, n, m;
int u, v, num, head[MAXN];
int team[MAXT], volk[MAXN];

inline void insert(int u, int v)
{
    t[++num].v=v;
    t[num].next=head[u];
    head[u]=num;
    t[++num].v=u;
    t[num].next=head[v];
    head[v]=num;
}
void solve()
{
    memset(head,0,sizeof(head));
    memset(volk,-1,sizeof(volk));
    num=0;
    readin(n);readin(m);
    for (int j=1; j<=m; j++)
    {
        readin(u);readin(v);
        insert(u,v);
    }
    team[1]=1;volk[team[1]]=1;
    int front=1,rear=2;
    for (; front!=rear; front=front%MAXT+1)
        for (int i=head[team[front]]; i!=0; i=t[i].next)
            if (volk[t[i].v]==-1)
            {
                team[rear]=t[i].v;
                volk[t[i].v]=volk[team[front]]^1;
                rear=rear%MAXT+1;
            }
            else if (volk[t[i].v]==volk[team[front]])
            {
                printf("NO\n");
                return ;
            }
    printf("YES\n");
} 
int main()
{
    freopen(PROGRAM_NAME".in","r",stdin);
    freopen(PROGRAM_NAME".out","w",stdout);
    readin(T);
    for (int i=1; i<=T; i++) solve();
    return 0;
}

第一题70,bfs。但以上程序有bug,只for了一遍死的很惨,要多for。
时间复杂度: O(n)

T2 book

#include <cstdio>
#include <algorithm>
#include <cstring>
#define PROGRAM_NAME "book"
using namespace std;
template<class TE>inline void readin(TE &res)
{
    char ch;
    while ((ch=getchar())<'0'||ch>'9');
    res=ch-'0';
    while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-'0';    
}
const int MAXN = 5000+100;
const int MAXM = 100000*2+1000;
const int MAXT = 5000+100;
struct Edge
{
    int v, w, next;
}t[MAXM];
int n, m, st, a[MAXN];
int u, v, w, num, head[MAXN];
int team[MAXT], dis[MAXN];
bool vis[MAXN];

inline void insert(int u, int v, int w)
{
    t[++num].v=v;
    t[num].w=w+a[u];
    t[num].next=head[u];
    head[u]=num;
}
int main()
{
    freopen(PROGRAM_NAME".in","r",stdin);
    freopen(PROGRAM_NAME".out","w",stdout);
    memset(head,0,sizeof(head));
    memset(dis,127/2,sizeof(dis));
    memset(vis,0,sizeof(vis));
    readin(n);readin(m);readin(st);
    for (int i=1; i<=n; i++) readin(a[i]);
    for (int j=1; j<=m; j++)
    {
        readin(u);readin(v);readin(w);
        insert(u,v,w);
        insert(v,u,w);
    }
    team[1]=st;dis[team[1]]=0;vis[team[1]]=1;
    for (int front=1,rear=2; front!=rear; front=front%MAXT+1)
    {
        for (int i=head[team[front]]; i!=0; i=t[i].next)
            if (dis[t[i].v]>dis[team[front]]+t[i].w)
            {
                dis[t[i].v]=dis[team[front]]+t[i].w;
                if (!vis[t[i].v])
                {
                    vis[t[i].v]=1;
                    team[rear]=t[i].v;
                    rear=rear%MAXT+1;
                }
            }
        vis[team[front]]=0;
    }
    int fm=0;
    for (int i=1; i<=n; i++) if (fm<dis[i]+a[i]) fm=dis[i]+a[i];
    printf("%d\n",fm>=dis[n+1]?-1:fm);
    return 0;
}

第二题AC,SPFA,点权+边权处理。点权加入边权,另需包扩终点点权。
时间复杂度: O(kE)

T3 TEACHER

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <iostream>
using namespace std;
#define PROGRAM_NAME "teacher"
using namespace std;
template<class TE>inline void readin(TE &res)
{
    char ch;
    while ((ch=getchar())<'0'||ch>'9');
    res=ch-'0';
    while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-'0';    
}
const int MAXN = 1000+100;
const int MAXW = 1000+100;
const int MAXT = 1000+100;
int n, m, T, w[MAXN], b[MAXN], fa[MAXN], u, v;
int volki=0, volk[MAXT], head[MAXT], next[MAXN], Min[MAXT], f[MAXW];
int find(int x)
{
    if (fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
inline void findi(int x)
{
    if (fa[x]==x) volk[x]=++volki;
    if (!volk[fa[x]]) findi(fa[x]);
    volk[x]=volk[fa[x]];
    Min[volk[x]]=min(Min[volk[x]],w[x]);
    next[x]=head[volk[x]];
    head[volk[x]]=x;
}
int main()
{
    freopen(PROGRAM_NAME".in","r",stdin);
    freopen(PROGRAM_NAME".out","w",stdout);
    memset(volk,0,sizeof(volk));
    memset(head,0,sizeof(head));
    memset(Min,127/2,sizeof(Min));
    memset(f,0,sizeof(f));
    readin(n);readin(m);readin(T);
    for (int i=1; i<=n; i++) readin(w[i]);
    for (int i=1; i<=n; i++) readin(b[i]);
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int j=1; j<=m; j++)
    {
        int u, v;
        readin(u);readin(v);
        u=find(u);
        v=find(v);
        if (u!=v) fa[u]=v;
    }
    for (int i=1; i<=n; i++) if (!volk[i]) findi(i);
    for (int i=1; i<=volki; i++)
    {
        int sumw=0,sumb=0;
        for (int j=head[i]; j!=0; j=next[j]) sumw+=w[j],sumb+=b[j];
        for (int W=T; W>=Min[i]; W--)
        {
            for (int j=head[i]; j!=0; j=next[j])
                if (W>=w[j]) f[W]=max(f[W],f[W-w[j]]+b[j]);
            if (W>=sumw) f[W]=max(f[W],f[W-sumw]+sumb);
        }
    }
    printf("%d\n",f[T]);
    return 0;
}

第三题AC,当时为了分组编了许久。先用并查集分组,再kij动规解决。
时间复杂度: O(nW)

经验与教训

练习赛是用来练经验和心态的,一定要淡薄功利,当作是一场修炼。林荫的人很“恐怖”,但千万不要妄自菲薄,更不要夜郎自大。现在所学的知识已有很多拓展,一定要跳出问题想问题,深处问题核心去解决问题。叶余非很强,可与之共勉。

附录1: model. cpp

#include <cstdio>
#include <algorithm>
#include <cstring>
#define PROGRAM_NAME ""
using namespace std;
template<class TE>inline void readin(TE &res)
{
    char ch;
    while ((ch=getchar())<'0'||ch>'9');
    res=ch-'0';
    while ((ch=getchar())>='0' && ch<='9')
        res=(res>>1)+(res>>3)+ch-'0';   
}
int main()
{
    freopen(PROGRAM_NAME".in","r",stdin);
    freopen(PROGRAM_NAME".out","w",stdout);
    return 0;
}

附录2: 修改后的color. cpp

#include <cstdio>
#include <algorithm>
#include <cstring>
#define PROGRAM_NAME "color"
using namespace std;
template<class TE>inline void readin(TE &res)
{
    char ch;
    while ((ch=getchar())<'0'||ch>'9');
    res=ch-'0';
    while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-'0';    
}
const int MAXN = 100000+10000;
const int MAXM = 250000*2+10000;
const int MAXT = 100000+10000;
struct Edge
{
    int v, next;
}t[MAXM];
int T, n, m;
int u, v, num, head[MAXN];
int team[MAXT], volk[MAXN];

inline void insert(int u, int v)
{
    t[++num].v=v;
    t[num].next=head[u];
    head[u]=num;
    t[++num].v=u;
    t[num].next=head[v];
    head[v]=num;
}
void solve()
{
    memset(head,0,sizeof(head));
    memset(volk,-1,sizeof(volk));
    num=0;
    readin(n);readin(m);
    for (int j=1; j<=m; j++)
    {
        readin(u);readin(v);
        insert(u,v);
    }
    for (int d=1; d<=n; d++) if (volk[d]==-1)
    {
        team[1]=d;volk[team[1]]=1;
        for (int front=1,rear=2; front!=rear; front=front%MAXT+1)
            for (int i=head[team[front]]; i!=0; i=t[i].next)
                if (volk[t[i].v]==-1)
                {
                    team[rear]=t[i].v;
                    volk[t[i].v]=volk[team[front]]^1;
                    rear=rear%MAXT+1;
                }
                else if (volk[t[i].v]==volk[team[front]])
                {
                    printf("NO\n");
                    return ;
                }
    }
    printf("YES\n");
}
int main()
{
    freopen(PROGRAM_NAME".in","r",stdin);
    freopen(PROGRAM_NAME".out","w",stdout);
    readin(T);
    for (int i=1; i<=T; i++) solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值