l2-4功夫传人
题意: 给定以1为根的有向树,根节点的点权为Z,每传给子节点,就减少r%,该子节点是叶子节点,叶子节点会翻a[i]倍。
思路: 感觉这个题意有点迷,题干说没传一代就减弱r%,除非遇到叶子,就说明叶子不该减弱r%。但是这样连样例都过不了,好怪。
建完图dfs求和即可。
!又忘了特判,如果n==1我又没特判,wa了一分。
时间复杂度: O(n)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+10;
int n,m,k,T;
// #define int long long
// #define double long double
double st;
double r;
double a[N];
double ans[N];
vector<int> va[N];
void dfs(int cur)
{
for(int i=0;i<va[cur].size();++i)
{
int j = va[cur][i];
if(a[j] != -1)
{
ans[j] = ans[cur] *(1.0-r) * a[j];
}
else
{
ans[j] = ans[cur] * (1.0-r);
dfs(j);
}
}
}
void solve()
{
cin>>n>>st>>r;
r *= 0.01;
for(int i=0;i<n;++i) a[i] = -1;
for(int i=0;i<n;++i)
{
int num; cin>>num;
int x;
if(num == 0)
{
cin>>a[i];
}
else
{
while(num--)
{
int x; cin>>x;
va[i].push_back(x);
}
}
}
if(n == 1 && a[0] != 0)
{
cout<<(int)(st*a[0]);
return ;
}
// cout<<(17.82*7)<<"\n";
double sum = 0;
ans[0] = st;
dfs(0);
for(int i=0;i<n;++i)
{
// cout<<i<<":"<<ans[i]<<"\n";
if(a[i] != -1)
{
sum += ans[i];
}
}
// cout<<(int)sum;
printf("%lld",(ll)sum);
}
signed main(void)
{
solve();
return 0;
}
l3-2周游世界
题意: 给定m条双向公交路线,给定k组查询,查询从st到ed的最短路径。如果路径不唯一,则输出换乘次数最少的路径。题目保证该路径唯一。注意:输出路径并不是输出从起点到终点的路径,而是输出每次换乘的起点和终点,以及最后一次不换乘到达终点的起点和终点。
思路: 当时心态有点小炸,感觉这题也太麻烦了,乱七八糟的。最短路可能不太好做这个题,而且数据量只有100,直接dfs即可。
1.建图,同一路线的相邻两点之间连边。而不是一个点连所有其他点。
2.用数组line[x][y]或者map记录一下从x走到y属于哪个线路。
3.dfs的时候记录路径,如果到达终点,遍历一遍路径求得换乘次数。
!dfs之前没有把起点加入路径,但是能过样例,一直wa。
时间复杂度: O(能过)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 9999+20;
#define mem(a,x) memset(a,x,sizeof(a))
int line[N][N];
bool vis[N];
int st,ed;
vector<int> va[N];
vector<int> v; //路径
vector<int> a; //答案
int ans = 1e9;
int res = 1e9;
int n,m,k,T;
int fun()
{
int cnt = 0;
int lst = 0;
for(int i=1;i<v.size();++i)
{
int l = v[i-1];
int r = v[i];
if(lst == 0)
{
lst = line[l][r];
}
else
{
if(lst != line[l][r])
{
cnt++;
lst = line[l][r];
}
}
}
return cnt-1;
}
void dfs(int cur,int num)
{
if(num > ans) return ;
if(cur == ed)
{
int c = fun();
if(num < ans)
{
ans = num;
res = c;
a = v;
}
else if(num == ans)
{
if(c < res)
{
res = c;
a = v;
}
}
return ;
}
for(int i=0;i<va[cur].size();++i)
{
int j = va[cur][i];
if(!vis[j])
{
vis[j] = 1;
v.push_back(j);
dfs(j,num+1);
v.pop_back();
vis[j] = 0;
}
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;++i)
{
int num; cin>>num;
vector<int> vv;
while(num--)
{
int x; cin>>x;
vv.push_back(x);
}
for(int j=1;j<vv.size();++j)
{
int l = vv[j-1];
int r = vv[j];
va[l].push_back(r);
va[r].push_back(l);
line[l][r] = line[r][l] = i;
}
}
cin>>k;
while(k--)
{
cin>>st>>ed;
ans = res = 1e9;
mem(vis,false); vis[st] = 1;
v.clear();
a.clear();
v.push_back(st);
dfs(st,0);
// cout<<ans<<"?\n";
if(ans == 1e9)
{
printf("Sorry, no line is available.\n");
}
else
{
printf("%d\n",ans);
int lst = 0;
int start = st;
for(int i=1;i<a.size();++i)
{
int l = a[i-1];
int r = a[i];
if(lst == 0)
{
lst = line[l][r];
}
else
{
if(lst != line[l][r])
{
printf("Go by the line of company #%d from %04d to %04d.\n",lst,start,l);
lst = line[l][r];
start = l;
}
}
}
printf("Go by the line of company #%d from %04d to %04d.\n",lst,start,ed);
}
}
}
signed main(void)
{
solve();
return 0;
}