程序设计天梯赛L3-22 (小丑竟是我自己)

题目
题意: 我一开始以为题意有问题,后来看了题解看了半天才看明白题意,小丑竟是我自己。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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值