【NOIP 2016】初赛-完善程序 & 参考答案
参考答案
感觉这两题目都挺好的~~
T1 交朋友
简单描述:有n个人依次进入教室,每个人进入会找一个身高绝对值相差最小的人交朋友(相同时更想和高的交朋友),求每个人交的朋友.
Solution:
Sort,求出每个人的排名
逆向思维,从后往前(每次删除,然后剩余的都是可以选的)
链表存储前一个和后一个,每次删除发生改变
发组福利数据
in:
6
4 6 5 3 1 7
out:
2:1
3:2
4:1
5:4
6:2
// <T1.cpp> - Sun Oct 23 22:05:36 2016 // This file is made by YJinpeng,created by XuYike's black technology automatically. // Copyright (C) 2016 ChangJun High School, Inc. // I don't know what this program is. #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #define INF 0x7fffffff using namespace std; const int MAXN=100010; inline int gi() { register int w=0,q=0;register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')q=1,ch=getchar(); while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar(); return q?-w:w; } int as[MAXN],rank[MAXN],h[MAXN],pre[MAXN],nex[MAXN]; bool cmp(int a,int b){return h[a]<h[b];} int main() { freopen("T1.in","r",stdin); freopen("T1.out","w",stdout); int n=gi(),s; for(int i=1;i<=n;i++)h[i]=gi(),rank[i]=i; sort(rank+1,rank+1+n,cmp); for(int i=1;i<=n;i++) pre[rank[i]]=rank[i-1],nex[rank[i]]=rank[i+1]; for(int i=n;i>=2;i--){ s=INF; if(!pre[i])s=h[i]-h[pre[i]]; if(!nex[i])s+=h[i]-h[nex[i]]; if(s<0)as[i]=pre[i]; else as[i]=nex[i]; nex[pre[i]]=nex[i]; pre[nex[i]]=pre[i]; } for(int i=2;i<=n;i++)printf("%d:%d\n",i,as[i]); return 0; }
T2 交通中断
大意:给一个无向图,问第x个点中断时(与其他点连边全部删掉),从1号点到多少个点的最短路改变(包括不能到达,不包括x)
Solution:
先求出1到每个点的最短路,然后举删掉了哪个点,从1开始bfs(到达的是最短路,加入队列),这样贪心保证正确性,因为一个点可能可以从多个点跑相同长度的最短路到达.
发组福利数据
in:
5 7
1 2 1
1 2 0
1 3 4
2 3 3
4 5 1
3 4 2
1 4 3
out:
2:1
3:0
4:1
5:0
// <T2.cpp> - Sun Oct 23 22:05:36 2016 // This file is made by YJinpeng,created by XuYike's black technology automatically. // Copyright (C) 2016 ChangJun High School, Inc. // I don't know what this program is. #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #define IN inline #define RG register #define INF 0x7fffffff using namespace std; inline int gi() { register int w=0,q=0;register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')q=1,ch=getchar(); while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar(); return q?-w:w; } struct SPFA{ static const int N=6010,M=100010; queue<int>q;bool u[N]; int n,m,t;int d[N],fr[N];int to[M],ne[M],W[M]; IN void link(RG int u,RG int v,RG int w){ to[++t]=v;ne[t]=fr[u];fr[u]=t;W[t]=w; } void read(){ n=gi(),m=gi(); while(m--){ int u=gi(),v=gi(),w=gi(); link(u,v,w);link(v,u,w); } } void Spfa(int begin){ for(int i=1;i<=n;i++)d[i]=INF; q.push(begin);d[begin]=0;memset(u,0,sizeof(u)); while(!q.empty()){ int x=q.front();q.pop();u[x]=0; for(int o=fr[x],y;y=to[o],o;o=ne[o]) if(d[x]+W[o]<d[y]){ d[y]=d[x]+W[o]; if(!u[y])u[y]=1,q.push(y); } } } void Work(){ read();Spfa(1); while(!q.empty())q.pop(); for(int i=2;i<=n;i++){ memset(u,0,sizeof(u)); q.push(1);u[1]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int o=fr[x],y;y=to[o],o;o=ne[o]) if(y!=i&&d[x]+W[o]==d[y]&&!u[y]) u[y]=1,q.push(y); }int ans=0; for(int j=1;j<=n;j++)ans+=1-u[j]; printf("%d:%d\n",i,ans-1); } } }e; int main() { freopen("T2.in","r",stdin); freopen("T2.out","w",stdout); e.Work(); return 0; }