个人博客:Eloi-还在前进.
A: Weather Forecast
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N;
string S;
cin>>N;
cin>>S;
if(S[N-1]=='o') cout<<"Yes";
else cout<<"No";
return 0;
}
B: qwerty
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a;
for(int i=1;i<=26;i++)
{
cin>>a;
printf("%c",'a'+a-1);
}
return 0;
}
C: Shapes
D: Rectangles
E: Destruction
tags:最小生成树
题意:给一个连通无向带负权图,M条边。
你从中取边,每取一个边,按照边权是否大于零给reward或fine。
让你计算,在保证取完后图联通的前提下,能获得的最大reward。
思路:
先计算不考虑保证联通情况下最大reward和。
逆向思维。
先不连边。
取一个最小生成树。
减去因最小生成树,而不得不舍弃的,最少reward。
即为答案。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int father[200005];
struct road
{
int x;
int y;
int w;
}r[200005];
int cmp(road x,road y)
{
return x.w<y.w;
}
int find_root(int x)
{
if(father[x]!=x)
{
father[x]=find_root(father[x]);
}
return father[x];
}
void merge(int x,int y)
{
int rx=find_root(x);
int ry=find_root(y);
father[rx]=ry;
}
int main()
{
long long sum=0;
int N,M;
cin>>N>>M;
for(int i=1;i<=N;i++)
{
father[i]=i;
}
for(int i=1;i<=M;i++)
{
cin>>r[i].x>>r[i].y>>r[i].w;
if(r[i].w>0) sum+=r[i].w;
}
sort(r+1,r+1+M,cmp);
for(int i=1;i<=M;i++)
{
if(find_root(r[i].x)!=find_root(r[i].y))
{
N--;
merge(r[i].x,r[i].y);
if(r[i].w>0) sum-=r[i].w;
}
if(N==1)
{
break;
}
}
cout<<sum;
return 0;
}
F: Blocked Roads
tags:最短路
题意:给你一个有向图,每条边权值为1。
让你计算在去除每条边,保留其他边时 ,从节点1至节点N的最短路。
解题思路:
上手看到最短路,首先想到四种最短路法: SPFA,Dijkstra,floyed,dp+topsort;
关于SPFA:单源最短路算法,可用于负权图及判断负环,其他类型的图不建议使用,
因其复杂度较不稳定,易被卡。
关于Dijkstra:单源最短路算法,可用于非负权图首选。
关于floyed:多源最短路算法,正负权图皆可,O(n^3).
关于dp+topsort:多用于最长路。DAG+可重边。
当然在路径长度随经过节点个数非递减时也可用BFS,
当然也就是题目中的情况,很明显比赛时我没想到 ,
当然除了写的慢点,也没别的问题 。
这里我们选用Dijkstra。
你可能会想,很简单,去除每条边后跑一遍Dijkstra.
这必TLE.
所以我们需要优化。
可以通过先跑一遍Dijkstra记录path和元最短路,
遍历边时,判断该边是否在最短路中,
不是的话直接输出元最短路。
是的话再跑一遍Dijkstra.
这样就ok了。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int N,M;
vector <int> path[405];
typedef pair <int,int> P;
priority_queue <P,vector<P>,greater<P> > q;
int MAP[405][405];
void dijkstra()
{
int dis[405]={0};
int vis[405]={0};
for(int i=1;i<=N;i++)
{
dis[i]=1e9;
}
q.push(P(0,1));
dis[1]=0;
while(!q.empty())
{
int from=q.top().second;
q.pop();
if(vis[from]) continue;
vis[from]=1;
for(int i=1;i<=N;i++)
{
if(MAP[from][i]==1)
{
if(dis[i]>dis[from]+1)
{
dis[i]=dis[from]+1;
q.push(P(dis[i],i));
}
}
}
}
if(dis[N]==1e9) cout<<-1<<endl;
else cout<<dis[N]<<endl;
}
int main()
{
int x[160005],y[160005];
cin>>N>>M;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
MAP[i][j]=1e9;
}
}
for(int i=1;i<=N;i++)
{
MAP[i][i]=0;
}
for(int i=1;i<=M;i++)
{
cin>>x[i]>>y[i];
MAP[x[i]][y[i]]=1;
}
//第一遍Dijkstra,记录path
int dis[405]={0};
int vis[405]={0};
for(int i=1;i<=N;i++)
{
dis[i]=1e9;
}
q.push(P(0,1));
dis[1]=0;
while(!q.empty())
{
int from=q.top().second;
q.pop();
if(vis[from]) continue;
vis[from]=1;
for(int i=1;i<=N;i++)
{
if(MAP[from][i]==1)
{
if(dis[i]>dis[from]+1)
{
path[from].push_back(i);
dis[i]=dis[from]+1;
q.push(P(dis[i],i));
}
}
}
}
//
for(int i=1;i<=M;i++)
{
bool flag=0;
for(auto k:path[x[i]])
{
if(k==y[i])
{
flag=1;
MAP[x[i]][y[i]]=1e9;
dijkstra();
MAP[x[i]][y[i]]=1;
}
}
if(flag==0)
{
if(dis[N]==1e9) cout<<-1<<endl;
else cout<<dis[N]<<endl;
}
}
return 0;
}