1寻找道路(题目链接)
这个题有点绕。我们可以通过从终点出发,将已知边反向,用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 ll mod=998244353;
using namespace std;
ll b[100010],a[100010],vis[100010],pis[100010],dis1[100010],dis[100010],tot=0,pot=0;
priority_queue<pair<ll,ll> >p;
deque<ll> q;
struct node
{
ll w,to,next;
}tz[800010],pz[800010];
void add1(ll x,ll y)
{
tz[++tot].w=1;
tz[tot].to=y;
tz[tot].next=a[x];
a[x]=tot;
}
void add2(ll x,ll y)
{
pz[++pot].w=1;
pz[pot].to=y;
pz[pot].next=b[x];
b[x]=pot;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,n,m,s,t;
cin>>n>>m;
memset(vis,0,sizeof(vis));
memset(pis,0,sizeof(pis));
for(i=0;i<=n;i++)
{
a[i]=b[i]=-1;
dis[i]=dis1[i]=1e12;
}
for(i=0;i<m;i++)
{
ll x,y;
cin>>x>>y;
if(x!=y)
{
add1(x,y);
add2(y,x);
}
}
cin>>s>>t;
q.push_back(t);
dis1[t]=0;
while(!q.empty())
{
ll x=q.front();
q.pop_front();
for(i=b[x];i!=-1;i=pz[i].next)
{
if(!pis[pz[i].to])
{
dis1[pz[i].to]=dis1[x]+1;
q.push_back(pz[i].to);
pis[pz[i].to]=1;
}
}
}
memcpy(vis,dis1,sizeof(dis1));
for(i=1;i<=n;i++)
{
if(vis[i]>=1e12)
for(j=b[i];j!=-1;j=pz[j].next)
{
if(vis[pz[j].to]!=1e12)
vis[pz[j].to]=1e12;
}
}
q.push_back(s);
dis[s]=0;
while(!q.empty())
{
ll x=q.front();
q.pop_front();
for(i=a[x];i!=-1;i=tz[i].next)
{
if(vis[tz[i].to]!=1e12)
{
dis[tz[i].to]=dis[x]+1;
q.push_back(tz[i].to);
vis[tz[i].to]=1e12;
}
}
}
if(dis[t]==1e12)
cout<<"-1";
else
cout<<dis[t];
return 0;
}
2 n的约数(题目链接)
这个题用dfs搜,对于一个数,可以拆成素数的幂次之积,约数个数则为(幂次+1)之积。但是注意数据特别大,需要及时判断是否超过已知数字大小(用除法判)。代码如下。
#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 ll mod=998244353;
using namespace std;
ll n,m,a[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51},ans=0;
void dfs(ll pos,ll len,ll zi,ll sum)
{
if(sum>n)
return;
if(sum<=n)
ans=max(ans,zi);
ll res=1,i;
for(i=1;i<=len;i++)
{
res*=a[pos];
dfs(pos+1,i,zi*(i+1),sum*res);
if(sum>n/res)
break;
}
return;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,s,t;
cin>>m;
for(i=0;i<m;i++)
{
cin>>n;
ans=0;
dfs(1,32,1,1);
cout<<ans<<endl;
}
return 0;
}
3经商(题目链接)
这个题比较简单,思路非常的清晰。先用并查集看有哪些人与小d认识,把认识的人的信息存入数组或者结构体中,然后用一个简单的背包dp就解决了。代码如下。
#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 ll mod=998244353;
using namespace std;
ll n,m,fa[100010],c,a[100010],b[100010],dp[100010];
struct node
{
ll v,w;
}p[100010];
ll fin(ll x)
{
if(fa[x]==x)
return x;
else
return fa[x]=fin(fa[x]);
}
void jia(ll x,ll y)
{
x=fin(fa[x]);
y=fin(fa[y]);
if(x!=y)
{
fa[x]=fa[y];
}
}
bool pan(ll x,ll y)
{
x=fin(fa[x]);
y=fin(fa[y]);
if(x==y)
return true;
else
return false;
}
int main()
{
ios::sync_with_stdio(false);
ll i,j,s,t;
cin>>t;
while(t--)
{
cin>>n>>m>>c;
for(i=0;i<=n;i++)
fa[i]=i;
for(i=1;i<n;i++)
{
cin>>a[i+1]>>b[i+1];
}
for(i=0;i<m;i++)
{
ll x,y;
cin>>x>>y;
jia(x,y);
}
j=0;
memset(dp,0,sizeof(dp));
for(i=2;i<=n;i++)
{
if(pan(1,i))
{
p[j].w=a[i];
p[j].v=b[i];
j++;
}
}
m=j;
for(i=0;i<=c;i++)
{
if(p[0].w<=i)
{
dp[i]=p[0].v;
}
}
for(i=1;i<m;i++)
{
for(j=c;j>=p[i].w;j--)
{
dp[j]=max(dp[j],dp[j-p[i].w]+p[i].v);
}
}
cout<<dp[c]<<endl;
}
return 0;
}