最简单的就是D题,Dijkstra模板题。
中文题。题意就是给一个无向图找两点之间的最短路。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxn = 100 + 5;
const int INF = 1<<30;
int n,m,a,b,c;
int pic[maxn][maxn];
int vis[maxn];
int d[maxn];
void dijkstra(int s, int e)
{
int pos,minn;
memset(vis,0,sizeof(vis));
d[s] = 0;
vis[s] = 1;
for(int i = 0; i < n; i++)//初始化i到起点的距离
d[i] = pic[s][i];
for(int i = 1; i < n; i++){
minn = INF;
//找出剩下未入选的点中距离源点最短的
for(int j = 0; j < n; j++){
if(d[j] < minn && !vis[j]){
pos = j;
minn = d[j];
}
}
vis[pos] = 1;
for(int j = 0; j < n; j++){
//更新加入该点后,所有点到源点的距离
if(d[pos]+pic[pos][j] < d[j] && !vis[j])
d[j] = d[pos] + pic[pos][j];
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n == 0 && m == 0) break;
for(int i = 0; i < maxn; i++){//初始化地图
for(int j = 0; j < maxn; j++)
pic[i][j] = INF;
pic[i][i] = 0;
}
while(m--){
scanf("%d%d%d",&a,&b,&c);
a--; b--;//统一下标从零开始
if(c < pic[a][b]) //更新两点间距离,可能有重复,选最短的
pic[a][b] = pic[b][a] = c;
}
dijkstra(0,n-1);
printf("%d\n",d[n-1]);
}
return 0;
}
然后就是E题。中文题。看成一个有向图,判断是否有冠军,就是判断是否存在一个入度为零的点,也很简单。主要处理名字比较麻烦,把名字都存在数组a中,此人在a[]中的下标对应in[]中的下标,也就是a[x]的入度为in[x]。每次在读入名字的时候判断它是否存在a[]中,然后对应处理in[]。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 2000 + 5;
struct node{
char s[20];
}a[maxn];
int in[maxn];
void solve(int k)//有一个入度为1的,则是冠军,否则没有
{
int cnt = 0;
for(int i = 1; i < k; i++)
if(in[i] == 0) cnt++;
if(cnt == 1) printf("Yes\n");
else printf("No\n");
}
int main()
{
int n,k,flag;
char s1[20],s2[20];
while(~scanf("%d",&n)){
if(n == 0) break;
memset(in,0,sizeof(in));
k = 1;
for(int i = 1; i <= n; i++){
flag = 0;
scanf("%s %s",s1,s2);
for(int j = 1; j < k; j++)//检查a[]中是否存在s1
if(strcmp(a[j].s,s1) == 0){
flag = 1;
break;
}
if(flag == 0){//不存在就存到a[]中
strcpy(a[k].s,s1);
k++;
}
flag = 0;
for(int j = 1; j < k; j++)
//a[]中有s2则入度加一,没有就存进去
if(strcmp(a[j].s,s2) == 0){
in[j]++;
flag = 1;
break;
}
if(flag == 0){
strcpy(a[k].s,s2);
in[k]++;
k++;
}
}
solve(k);
}
return 0;
}
接着就是B题,无力吐槽自己的英文读题能力。
题意:把所有的路和城市看作一棵树,每个城市(除了首都)都有一个从首都到它的索引,也就是它的前驱。然后现在换一个首都,也就是换一个树根,按顺序输出按照那个规则的现在每个城市的索引。
思路:别的不变,只需要改变从原本根节点出来的路的方向就行了。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 50000 + 5;
int n,r1,r2,x;
vector<int> a[maxn];
int p[maxn];
int vis[maxn];
void dfs(int i)
{
vis[i] = 1;
for(int j = 0; j < a[i].size(); j++){
int v = a[i][j];
if(!vis[v]){
p[v] = i;
dfs(v);
}
}
}
int main()
{
while(~scanf("%d%d%d",&n,&r1,&r2)){
memset(p,0,sizeof(p));
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++){
if(i == r1) continue;
scanf("%d",&x);
a[i].push_back(x);
a[x].push_back(i);
}
dfs(r2);
int flag = 0;
for(int i = 1; i <= n; i++){
if(i == r2) continue;
if(flag) printf(" ");
printf("%d",p[i]);
flag++;
}
printf("\n");
}
return 0;
}
另外几题有时间再补。。。