最近在学最短路啊,给你们看一下我犯过的致命错误。持续更新······
1.数组大小没开够,RE
P8802出差
#include<bits/stdc++.h>
using namespace std;
long long n,m,dis[1005];
long long tot,c[1005];
struct node{
long long u,v,d;
}e[6005];
void bellman_ford(){
for(int i=1;i<=n;i++){
for(int j=1;j<=tot;j++){
int u=e[j].u,v=e[j].v,w=e[j].d;
if(v!=n){
dis[v]=min(dis[v],dis[u]+w+c[v]);
}else{
dis[v]=min(dis[v],dis[u]+w);
}
}
}
}
int main(){
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> c[i];
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
tot++;
e[tot].u=u;
e[tot].v=v;
e[tot].d=w;
tot++;
e[tot].u=v;
e[tot].v=u;
e[tot].d=w;
}
bellman_ford();
cout << dis[n];
return 0;
}
用的Bellman-ford,因为没看数据大小,导致RE了9个点,只拿了10分。在考场上直接同时省一。
AC代码
#include<bits/stdc++.h>
using namespace std;
long long n,m,dis[1005];
long long tot,c[1005];
struct node{
long long u,v,d;
}e[20005];
void bellman_ford(){
for(int i=1;i<=n;i++){
for(int j=1;j<=tot;j++){
int u=e[j].u,v=e[j].v,w=e[j].d;
if(v!=n){
dis[v]=min(dis[v],dis[u]+w+c[v]);
}else{
dis[v]=min(dis[v],dis[u]+w);
}
}
}
}
int main(){
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> c[i];
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
tot++;
e[tot].u=u;
e[tot].v=v;
e[tot].d=w;
tot++;
e[tot].u=v;
e[tot].v=u;
e[tot].d=w;
}
bellman_ford();
cout << dis[n];
return 0;
}
还有个Dij的,没学Bellman-ford的同学可以
抄研究一下。
#include<bits/stdc++.h>
using namespace std;
int n,m,dis[1005],head[1005],tot;
int c[1005];
bool vis[1005];
struct Edge{
int nex,dis,to;
}e[20005];
struct node{
int pos,dis;
};
void add(int u,int v,int w){
tot++;
e[tot].nex=head[u];
e[tot].to=v;
e[tot].dis=w;
head[u]=tot;
}
bool operator <(node x,node y){
return x.dis>y.dis;
}
priority_queue<node> q;
void dij(){
node st;
st.pos=1;
st.dis=0;
dis[1]=0;
q.push(st);
while(!q.empty()){
node ind=q.top();
q.pop();
int u=ind.pos;
if(vis[u]){
continue;
}
vis[u]=1;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to,w=e[i].dis+c[v];
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
ind.dis=dis[v];
ind.pos=v;
q.push(ind);
}
}
}
}
int main(){
cin >> n >> m;
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=n;i++){
cin >> c[i];
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
add(u,v,w);
add(v,u,w);
}
dij();
cout << dis[n]-c[n];
return 0;
}
2.多测不清空,吃席在家中
P3385
#include<bits/stdc++.h>
using namespace std;
int n,m,dis[3005],tot,head[3005],cnt[3005];
struct Edge{
int nex,dis,to;
}e[6010];
bool vis[3005],tf;
void add(int u,int v,int w){
tot++;
e[tot].dis=w;
e[tot].nex=head[u];
e[tot].to=v;
head[u]=tot;
}
queue<int>q;
void spfa(){
dis[1]=0;
q.push(1);
vis[1]=1;
while(!q.empty()){
int pos=q.front();
q.pop();
vis[pos]=0;
for(int i=head[pos];i;i=e[i].nex){
int v=e[i].to,w=e[i].dis;
if(dis[v]>dis[pos]+w){
dis[v]=dis[pos]+w;
if(!vis[v]){
cnt[v]=cnt[pos]+1;
if(cnt[v]>n){
cout << "YES" << endl;
return;
}
vis[v]=1;
q.push(v);
}
}
}
}
cout << "NO" << endl;
}
int main(){
int t;
cin >> t;
while(t--){
cin >> n >> m;
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
while(!q.empty()){
q.pop();
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
add(u,v,w);
add(v,u,w);
}
memset(vis,0,sizeof(vis));
spfa();
}
return 0;
}
两个问题啊,第一,head数组和tot变量都没有清空,导致了RE;第二,没看清题目要求,把所有边都建成了双向的。大家应以为戒
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,dis[3005],tot,head[3005],cnt[3005];
struct Edge{
int nex,dis,to;
}e[6010];
bool vis[3005],tf;
void add(int u,int v,int w){
tot++;
e[tot].dis=w;
e[tot].nex=head[u];
e[tot].to=v;
head[u]=tot;
}
queue<int>q;
void spfa(){
dis[1]=0;
q.push(1);
vis[1]=1;
while(!q.empty()){
int pos=q.front();
q.pop();
vis[pos]=0;
for(int i=head[pos];i;i=e[i].nex){
int v=e[i].to,w=e[i].dis;
if(dis[v]>dis[pos]+w){
dis[v]=dis[pos]+w;
cnt[v]=cnt[pos]+1;
if(cnt[v]>n){
cout << "YES" << endl;
return;
}
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
cout << "NO" << endl;
}
int main(){
int t;
cin >> t;
while(t--){
cin >> n >> m;
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(head,0,sizeof(head));
tot=0;
while(!q.empty()){
q.pop();
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
add(u,v,w);
if(w>=0){
add(v,u,w);
}
}
memset(vis,0,sizeof(vis));
spfa();
}
return 0;
}
还有一版Bellman-ford的,老规矩,直接拿走,但是挑自己会的知识点拿,不要露馅儿。因为Dij不能处理负环,所以只能用Bellman-ford或者Spfa。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int n,m,t,tot;
long long dis[50005];
struct edge{
int u,v,w;
}e[100050];
bool bellman_ford(){
for(int i=1;i<=n;i++){
for(int j=1;j<=tot;j++){
int u=e[j].u,v=e[j].v,w=e[j].w;
if(dis[u]<INF){
dis[v]=min(dis[v],dis[u]+w);
}
}
}
for(int j=1;j<=tot;j++){
int u=e[j].u,v=e[j].v,w=e[j].w;
if(dis[u]<INF&&dis[v]>dis[u]+w){
return 0;
}
}
return 1;
}
int main(){
cin >> t;
while(t--){
memset(dis,INF,sizeof(dis));
tot=0;
cin >> n >> m;dis[1]=0;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
tot++;
if(w>=0){
e[tot].u=u;
e[tot].v=v;
e[tot].w=w;
tot++;
e[tot].u=v;
e[tot].v=u;
e[tot].w=w;
}else{
e[tot].u=u;
e[tot].v=v;
e[tot].w=w;
}
}
bool tf=bellman_ford();
if(tf){
cout << "NO" << endl;
}else{
cout << "YES" << endl;
}
}
return 0;
}
3.数组开的太大,爆零了解一下
P1629 邮递员送信
#include<bits/stdc++.h>
using namespace std;
int n,m,mapp[100005][100005],ans;
int main(){
memset(mapp,0x3f,sizeof(mapp));
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
mapp[u][v]=min(mapp[u][v],w);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mapp[i][j]=min(mapp[i][k]+mapp[k][j],mapp[i][j]);
}
}
}
for(int i=2;i<=n;i++){
ans+=(mapp[i][1]+mapp[1][i]);
}
cout << ans;
return 0;
}
一维数组最大可以开到4亿,二维数组最大可以开到[20000][20000],在大就会爆。
(提前声明,本代码不保证在linux系统操作环境下能运行)
#include<bits/stdc++.h>
using namespace std;
int n,m,mapp[1005][1005],ans;
int main(){
memset(mapp,0x3f,sizeof(mapp));
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
mapp[u][v]=min(mapp[u][v],w);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mapp[i][j]=min(mapp[i][k]+mapp[k][j],mapp[i][j]);
}
}
}
for(int i=2;i<=n;i++){
ans+=mapp[i][1]+mapp[1][i];
}
cout << ans;
return 0;
}
总结
考试的时候一定要注意细节,任何一个小错误都有可能葬送了一场比赛。以上列举的所有问题都是会丢大分的。因为RE,我丢了90分;因为多测不清空,我丢了90分;因为数组开太大,我爆零了。所以,一定要多看数据范围,测试点,开数组的时候一定要注意,太多分了。有90分我可能都省一了,甚至进省队了,这可都是辛酸血泪啊!