今天这套题是需要反省的,因为前三题在考试时我的第一思路出得很快,而且居然和正解一样,却在最后只AC了第三题。十分可惜,也需要沉重反省。。。
Span (Standard IO)
Time Limits: 1000 ms Memory Limits: 128000 KBDescription
某国有N个村子,M条道路,为了实现“村村通工程”现在要”油漆”N-1条道路(因为某些人总是说该国所有的项目全是从国外进口来的,只是漆上本国的油漆罢了),因为“和谐”是此国最大的目标和追求,以致于对于最小造价什么的都不在乎了,只希望你所选出来的最长边与最短边的差越小越好。
Input
第一行给出一个数字TOT,代表有多少组数据,Tot<=6
对于每组数据,首先给出N,M
下面M行,每行三个数a,b,c代表a村与b的村道路距离为c.
Output
输出最小差值,如果无解输出”-1”.
Sample Input
1
4 5
1 2 3
1 3 5
1 4 6
2 4 6
3 4 7
Sample Output
1
Data Constraint
Hint
【样例解释】
选择1-4,2-4,3-4这三条边.
【数据范围】
1:2 ≤ n ≤ 100 and 0 ≤ m ≤ n(n − 1)/2
2:每条边的权值小于等于10000
3:保证没有自环,没有重边
一开始想到就是枚举最短边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); }