2019牛客暑期多校训练营(第四场)J-free

题目链接:https://ac.nowcoder.com/acm/contest/884/J
题意:给你n个顶点的图,能把期中k条边置为0,给定起点,终点,求最短路
题解:把它当成一个k+1层的图,到下一层时,这条边的值为0,dis[i][j]表示第j层,起点到第i个点的距离,可以用spfa

#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;
ll dis[1050][1050], vis[1050][1050];

struct node
{
	ll to, val;
};

vector<node>v[1050];

void spfa(ll s, ll k)
{
	memset(dis, 0x3f3f3f3f3f3f3f3f, sizeof(vis));
	memset(vis, 0, sizeof(vis));
	dis[s][0] = 0;
	vis[s][0] = 1;
	queue<ll>q;
	q.push(s);
	q.push(0);
	while (!q.empty())
	{
		ll u = q.front(); q.pop();
		ll j = q.front(); q.pop();
		for (ll i = 0; i<v[u].size(); i++)
		{
			ll vv = v[u][i].to;
			if (dis[u][j] + v[u][i].val<dis[vv][j])
			{
				dis[vv][j] = dis[u][j] + v[u][i].val;
				if (!vis[vv][j])
				{
					vis[vv][j] = 1;
					q.push(vv);
					q.push(j);
				}
			}
			if (j<k&&dis[u][j]<dis[vv][j + 1])
			{
				dis[vv][j + 1] = dis[u][j];
				if (!vis[vv][j + 1])
				{
					vis[vv][j + 1] = 1; 
					q.push(vv);
					q.push(j + 1);
				}
			}
		}
		vis[u][j] = 0;
	}
}

int main()
{
	ll n, m, s, t, k;
	scanf("%lld %lld %lld %lld %lld", &n, &m, &s, &t, &k);
	for (int i = 1; i <= m; i++)
	{
		ll x, y, z;
		scanf("%lld %lld %lld", &x, &y, &z);
		v[x].push_back({ y,z });
		v[y].push_back({ x,z });
	}
	spfa(s, k);
	ll ansmin = 0x3f3f3f3f3f3f3f3f;
	for (ll i = 0; i <= k; i++)
	{
		ansmin = min(ansmin, dis[t][i]);
	}
	printf("%lld\n", ansmin);
}

你可能感兴趣的:(图论)