今天这套题是需要反省的,因为前三题在考试时我的第一思路出得很快,而且居然和正解一样,却在最后只AC了第三题。十分可惜,也需要沉重反省。。。
Span (Standard IO)
Time Limits: 1000 ms Memory Limits: 128000 KB3:保证没有自环,没有重边
一开始想到就是枚举最短边kruskal。但想想似乎复杂度O(tot*m^2)过不了。于是,我开始探究更高深的方法。
最后,觉得这复杂度只允许我贪心了,或许贪心就是正解,当然,我自己都觉得自己策略不好,但我像中了邪一般去赌一把。这就是挂科的根本原因。
最后看到正解,我跪了,居然就是枚举。
这次教训告诉我,唯稳方能胜,不要去做没把握的事。
无聊的草稿 (Standard IO)
Time Limits: 3000 ms Memory Limits: 128000 KB
Goto ProblemSet
Description
图中有N个点,每两点间只有唯一的路径,对于这样一个给定的图,最大的“毛毛虫”会有多大。毛毛虫包含一条主链,毛毛虫中的节点,要不在主链上,要么和主链上某节点相邻,如下图所示有两只合法的毛毛虫,点数越多,毛毛虫越大。
Input
输入文件第一行两个整数N,M(N≤1000000)
接下来M行,每行两个整数a, b(a, b≤N)
你可以假定没有一对相同的(a, b)会出现一次以上。
Output
一个整数ans,表示最大的毛毛虫的大小。
Sample Input
5 4
1 2
1 3
4 1
5 1
Sample Output
5
Data Constraint
Hint
【数据规模】
1. 对于20%的数据,N≤200
2. 对于40%的数据,N≤5000
3. 对于100%的数据,N≤10^6
当时看到题目第一反应是最长链时,因为第一题的题目描述激发了我丰富的想象力,早在做第一题时,我海里就已荡漾着最长链这个东西。但是,我却先去做了第三题。而第一题的猥琐方法耗费了不少时间。后面所剩不多的时间虽然够打完这题,但我去检验第三题了。
考完后,当我看到最长链是正解时,我和我的小心脏都惊呆了。
以下是我ac的程序
#include
#include
#include
using namespace std;
struct link{
int l,y;
}f[2000001];
int i,j,k,x,y,n,m,g[1000001],dep,ans,q[1000001],se[1000001],d[1000001];
bool v[1000001];
void dfsI(int p,int sum,int dep){
int i,j,k;
k=g[p];
q[dep]=p;
v[p]=0;
if(dep==1)j=d[p];else j=d[p]-1;
while(k){
if(v[f[k].y])dfsI(f[k].y,sum+j,0);
k=f[k].l;
}
if(sum>ans)ans=sum,x=p;
}
int main(){
scanf("%d%d",&n,&m);
int tot=0;
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
f[++tot].y=y;
f[tot].l=g[x];
g[x]=tot;
f[++tot].y=x;
f[tot].l=g[y];
g[y]=tot;
d[x]++;d[y]++;
}
memset(v,1,sizeof(v));
ans=0;
dfsI(1,1,1);
memset(v,1,sizeof(v));
ans=0;
dfsI(x,1,1);
printf("%d",ans);
}
锻炼身体 (Standard IO)
Time Limits: 1000 ms Memory Limits: 128000 KB
Description
胖子很有钱。他购买了一个先进的跑步机(真的不一样哦~~~~)。
这个跑步机是这样的:
1. 可以把它看成一个N*M的矩阵。有的格子是障碍不能经过(用x表示),有的格子是空地可以经过(用.表示)。
2. 对于每一个时段,跑步机有不同的倾斜方向。由于胖子太胖了,所以他这个时候只有2种选择:要么沿这个方向移动(每秒移动1个格子),或者艰难的保持在原来的位置不动。
现在胖子已经设定好了跑步机在不同时段中的倾斜方向。众所周知,保持在原地不动是不会做功的。胖子要减肥就要做功。所以他想知道他最多能够跑多长的路程。
Input
第一行5个正整数N,M,X,Y,K。 X,Y是胖子的初始位置,数据保证这个点不是障碍。
接下来N行,每行M个字符,表示跑步机上的地形。
最后K行,每行3个正整数S,T,W。S表示这个时段的开始时间,T(T<=10000)表示这个时段的结束时间。W表示该时段的倾斜方向。(1:上 2:下 3:左 4:右)
Output
一个整数LEN,表示胖子最多可以跑动的距离。
Sample Input
4 5 4 1 3
..xx.
.....
...x.
.....
1 3 4
4 5 1
6 7 2
Sample Output
6
【数据范围】
对于60%的数据 N,M<=80 K<=50
对于100%的数据 N,M<=200,K<=200
这题打的时候我还边打边加防止粗心的注释,最后打的也挺细心的。这次唯一的优点要发扬光大啊、、、
Dp
F[i][x][y]指在时段i,(x,y)点的最大做功。
明显F[i][x][y]=max(F[i][x][y],F[i][x][k]+Abs(y-k))//举例:当倾斜向左右上时,行号不变,列号 y-k>Ti-Si+1.
看到这条会超时的方程如此华丽,搞得我忍不住去优化一下它了。
设 F[i][x][j]+y-j>F[i][x][k]+y-k
F[i][x][j]-F[i][x][k]>j-k
于是可以用这个不等式建单调队列优化Dp,然后就ac了。
附上代码::
#include
#include
#include
#include
using namespace std;
struct node{
int s,t,w;
}s[202];
int i,j,k,x,y,n,m,q/*[2]*/[202][2],f[202][202][202];
bool v[202][202];
char e;
bool cmp(node a , node b){
return a.s=1;y--){
int l=2,r=1;
for(x=n;x>=1;x--){//sidejugdeCaution
if(v[x][y]){
l=2;r=1;
q[l][1]=-1;
continue;
}
while(abs(x-q[l][0])>s[i].t-s[i].s+1&&l<=r)l++;
if(f[i-1][x][y]!=-1){
while(f[i-1][x][y]-q[r][1]>abs(x-q[r][0])&&r>=l)r--;
r++;
q[r][1]=f[i-1][x][y];
q[r][0]=x;
}
if(q[l][1]!=-1&&l<=r)f[i][x][y]=q[l][1]+abs(x-q[l][0]);
}
}
if(s[i].w==2)
for(y=m;y>=1;y--){
int l=2,r=1;
for(x=1;x<=n;x++){//sidejugdeCaution
if(v[x][y]){
l=2;r=1;
q[l][1]=-1;
continue;
}
while(abs(x-q[l][0])>s[i].t-s[i].s+1&&l<=r)l++;
if(f[i-1][x][y]!=-1){
while(f[i-1][x][y]-q[r][1]>abs(x-q[r][0])&&r>=l)r--;
r++;
q[r][1]=f[i-1][x][y];
q[r][0]=x;
}
if(q[l][1]!=-1&&l<=r)f[i][x][y]=q[l][1]+abs(x-q[l][0]);
}
}
if(s[i].w==3)
for(x=n;x>=1;x--){
int l=2,r=1;
for(y=m;y>=1;y--){//sidejugdeCaution
if(v[x][y]){
l=2;r=1;
q[l][1]=-1;
continue;
}
while(abs(y-q[l][0])>s[i].t-s[i].s+1&&l<=r)l++;
if(f[i-1][x][y]!=-1){
while(f[i-1][x][y]-q[r][1]>abs(y-q[r][0])&&r>=l)r--;
r++;
q[r][1]=f[i-1][x][y];
q[r][0]=y;
}
if(q[l][1]!=-1&&l<=r)f[i][x][y]=q[l][1]+abs(y-q[l][0]);
}
}
if(s[i].w==4)
for(x=n;x>=1;x--){
int l=2,r=1;
for(y=1;y<=m;y++){//sidejugdeCaution
if(v[x][y]){
l=2;r=1;
q[l][1]=-1;
continue;
}
while(abs(y-q[l][0])>s[i].t-s[i].s+1&&l<=r)l++;
if(f[i-1][x][y]!=-1){
while(f[i-1][x][y]-q[r][1]>abs(y-q[r][0])&&r>=l)r--;
r++;
q[r][1]=f[i-1][x][y];
q[r][0]=y;
}
if(q[l][1]!=-1&&l<=r)f[i][x][y]=q[l][1]+abs(y-q[l][0]);
}
}
memset(q,255,sizeof(q));
}
int ans;
ans=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
ans=max(ans,f[k][i][j]);
}
printf("%d",ans);
}