题目
题意: 我一开始以为题意有问题,后来看了题解看了半天才看明白题意,小丑竟是我自己。n个点,m条线路,每条线路给出若干条边,费用变化为每走k便加1。给定T个询问,以T为起点可以到达多少个可以拍照的点。可以在费用相同的最远距离的点、线路端点处进行拍照。而且我们可以通过在多条线路中都出现的点在这些线路中切换。在起点处也能拍照。解释不太清楚,反正挺离谱。
思路: floyd处理最短路,Dij应该也行。然后dfs求出所有满足条件的点。而且这个输入还卡了我一个段错误,换成while getchar就行了,属于是不明白。
时间复杂度: O(n^3 + n)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1002;
const int INF = 0x3f3f3f3f;
int n,m,k,T;
bool line[N];
int a[N][N];
vector<int> va[N]; //点i可以到的费用相同的最远的点和端点
map<int,int> mp; //费用i对应的最远的点
bool vis[N];
void floyd()
{
for(int k=1;k<=n;++k)
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
a[i][j] = min(a[i][j],a[i][k] + a[k][j]);
}
}
}
}
void dfs(int u)
{
for(auto item:va[u])
{
if(!vis[item])
{
vis[item] = 1;
dfs(item);
}
}
}
void solve()
{
// ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(i==j) a[i][j] = 0;
else a[i][j] = INF;
}
}
for(int i=0;i<m;++i)
{
int x,y,z; char ch;
cin>>x;
line[x] = 1;
while(getchar() != '\n')
{
cin>>z>>y;
a[x][y] = min(a[x][y],z);
a[y][x] = min(a[y][x],z);
x = y;
}
line[x] = 1;
}
floyd();
for(int i=1;i<=n;++i)
{
mp.clear();
for(int j=1;j<=n;++j)
{
if(i != j)
{
if(a[i][j] == INF) continue;
mp[2+a[i][j]/k] = max(mp[2+a[i][j]/k],a[i][j]);
if(line[j])
{
va[i].push_back(j);
}
}
}
for(int j=1;j<=n;++j)
{
if(a[i][j] != INF && a[i][j] == mp[2+a[i][j]/k])
{
va[i].push_back(j);
}
}
}
cin>>m;
while(m--)
{
int x; cin>>x;
memset(vis,false,sizeof(vis));
vis[x] = 1;
dfs(x);
bool ok = true;
for(int i=1;i<=n;++i)
{
if(vis[i])
{
if(ok) ok = false;
else cout<<' ';
cout<<i;
}
}
cout<<endl;
}
}
signed main(void)
{
solve();
return 0;
}