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;
}