1Travel(题目链接)
这个题具有迷惑性,传送的路只有很少,但是点有很多。对于起点到终点来说,只有走这些有传送路的点才可能缩短路径,所以只需要对这些点进行操作即可,这些点可能很大,所以根据数据的特性可以进行哈希。对于这些特殊的点可以通过佛洛依德算法来求内部的最短路,如此一来从起点到终点的最短路只可能经过俩个特殊点。最后,这是个类似环状的题,俩个点的距离需要从俩个方向计算,取最小值。具体代码如下。
#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#include<sstream>
#define ll long long int
const int mod=1e9+7;
using namespace std;
ll a[200010],b[200010],sum[200010],n,m,r[50][50];
struct node
{
ll u,v,w;
}t[200];
ll dis(ll i,ll j)
{
if(i<j)
swap(i,j);
ll an=min(sum[i]-sum[j],sum[n+1]+sum[n]-sum[i]+sum[j]);
return an;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,x,y,z,s,k,cnt=0;
cin>>n>>m;
for(i=1;i<=n;i++)
cin>>a[i];
sum[1]=0;
for(i=2;i<=n;i++)
sum[i]=sum[i-1]+a[i-1];
sum[n+1]=a[n];
for(i=0;i<m;i++)
{
cin>>t[i].u>>t[i].v>>t[i].w;
b[cnt++]=t[i].u;
b[cnt++]=t[i].v;
}
cin>>s;
sort(b,b+cnt);
cnt=unique(b,b+cnt)-b;
for(i=0;i<cnt;i++)
for(j=0;j<cnt;j++)
{
r[i][j]=r[j][i]=dis(b[i],b[j]);
}
for(i=0;i<m;i++)
{
x=lower_bound(b,b+cnt,t[i].u)-b;
y=lower_bound(b,b+cnt,t[i].v)-b;
r[x][y]=r[y][x]=min(r[x][y],t[i].w);
}
for(k=0;k<cnt;k++)
for(i=0;i<cnt;i++)
for(j=0;j<cnt;j++)
r[i][j]=min(r[i][j],r[i][k]+r[k][j]);
for(i=0;i<s;i++)
{
cin>>x>>y;
z=dis(x,y);
for(j=0;j<cnt;j++)
for(k=0;k<cnt;k++)
z=min(z,dis(x,b[j])+dis(b[k],y)+r[k][j]);
cout<<z<<endl;
}
return 0;
}
2小欧的烦恼(题目链接)
由于最近太忙了,今天认真的做了这个题以后只过了一半的数据但是来不及改了,自己代码如下,明天修改。
#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#include<sstream>
#define ll long long int
const int mod=1e9+7;
using namespace std;
ll a[20],b[20],n,m,u,v,ma,shu[20],ans=100000000,anp=0;
queue<pair<ll,ll> >p;
int bfs()
{
p.push(make_pair(u,shu[u]));
if((u*10+v)%n==0)
{
ll sm=shu[u]+shu[v];
cout<<sm;
return 0;
}
while(!p.empty())
{
ll x=p.front().first,y=p.front().second;
p.pop();
if(x>1e7)
break;
for(int i=0;i<10;i++)
{
if(shu[i]!=0)
{
ll xi=x*10+i,yi=y+shu[i];
if((xi*10+v)%n==0)
{
ll xz=xi*10+v,yz=yi+shu[v];
if(ans>yz)
{
ans=yz;
anp=xz;
}
}
p.push(make_pair(xi,yi));
}
}
}
if(ans>=1e8)
return 1;
else
return 0;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,x,y,z,s,k,cnt=0;
memset(shu,0,sizeof(shu));
cin>>n>>m>>s;
n=__gcd(n,m);
for(i=0;i<s;i++)
cin>>a[i];
for(i=0;i<s;i++)
cin>>b[i];
for(i=0;i<s;i++)
shu[a[i]]=b[i];
cin>>u>>v;
if(bfs())
{
cout<<-1;
}
else
cout<<anp;
return 0;
}
看过博客以后自己写的代码,总之这个题里面的东西还是挺多的(对于一个蒻蒻来说),bfs的每一次操作取模就是高精度取模的思想,取模过后减少了数据量,得以用最短路的方法做这个题。已过代码如下。
#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#include<sstream>
#define ll long long int
const int mod=1e9+7;
using namespace std;
ll e,a[200010],b[200100],n,m,ma,shu[20],ans=100000000,anp=0,uu,vv,dis[200010],s,v[20],wp[20];
struct node
{
ll v,w;
bool operator <(const node &p) const
{
return p.w<w;
}
};
void prin(ll x)
{
if(a[x]==-1)
{
cout<<uu;
return;
}
prin(a[x]);
cout<<b[x];
}
priority_queue<node>p;
ll bfs(ll x)
{
int i;
for(i=0;i<200010;i++)
dis[i]=1000000000;
dis[x]=0;
a[x]=-1;
p.push({x,0});
while(!p.empty())
{
ll xz=p.top().v,yz=p.top().w;
p.pop();
if((xz*10+vv)%n==0)
{
prin(xz);
cout<<vv;
return 0;
}
for(i=0;i<10;i++)
{
if(wp[i])
{
ll np=(xz*10+i)%n;
if(dis[np]>dis[xz]+wp[i])
{
dis[np]=dis[xz]+wp[i];
a[np]=xz;
b[np]=i;
p.push({np,dis[np]});
}
}
}
}
return 1;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,x,y,z,k,cnt=0;
memset(wp,0,sizeof(wp));
cin>>n>>m>>s;
n=__gcd(n,m);
for(i=0;i<s;i++)
cin>>v[i];
for(i=0;i<s;i++)
cin>>wp[v[i]];
cin>>uu>>vv;
if(bfs(uu%n))
cout<<-1;
return 0;
}