The Preliminary Contest for ICPC Asia Nanjing 2019——H.Holy Grail(最短路)

As the current heir of a wizarding family with a long history,unfortunately, you find yourself forced to participate in the cruel Holy Grail War which has a reincarnation of sixty years.However,fortunately,you summoned a Caster Servant with a powerful Noble Phantasm.When your servant launch her Noble Phantasm,it will construct a magic field,which is actually a directed graph consisting of n vertices and m edges.More specifically,the graph satisfies the following restrictions :
Does not have multiple edges(for each pair of vertices x and y, there is at most one edge between this pair of vertices in the graph) and does not have self-loops(edges connecting the vertex with itself).
May have negative-weighted edges.
Does not have a negative-weighted loop.n<=300 , m<=500.
Currently,as your servant’s Master,as long as you add extra 6 edges to the graph,you will beat the other 6 masters to win the Holy Grail.
However,you are subject to the following restrictions when you add the edges to the graph:
Each time you add an edge whose cost is c,it will cost you c units of Magic Value.Therefore,you need to add an edge which has the lowest weight(it’s probably that you need to add an edge which has a negative weight).
Each time you add an edge to the graph,the graph must not have negative loops,otherwise you will be engulfed by the Holy Grail you summon.

Input
data contains multiple test cases.
The first line of input contains integer t — the number of testcases (1≤t≤5).
For each test case,the first line contains two integers n,m,the number of vertices in the graph, the initial number of edges in the graph.Then m lines follow, each line contains three integers x, y and w (0≤x,y<n,−109-10^9−109 ≤ w ≤10910^9109, x!=y) denoting an edge from vertices x to y (0-indexed) of weight w.
Then 6 lines follow, each line contains two integers s,t denoting the starting vertex and the ending vertex of the edge you need to add to the graph.It is guaranteed that there is not an edge starting from s to t before you add any edges and there must exists such an edge which has the lowest weight and satisfies the above restrictions, meaning the solution absolutely exists for each query.

Output
For each test case,output 666 lines.Each line contains the weight of the edge you add to the graph.

样例输入

1
10 15
4 7 10
7 6 3
5 3 3
1 4 11
0 6 20
9 8 25
3 0 9
1 2 15
9 0 27
5 2 0
7 3 -5
1 7 21
5 0 1
9 3 16
1 8 4
4 1
0 3
6 9
2 1
8 7
0 4

样例输出

-11
-9
-45
-15
17
7

题意:给你一个 n个点 m条边的有向图,并且保证图中没有负环和重边,需要让你添加6条边的权值,要满足添加后也没有负环,且 权值最小。

题解:没有负环且权值最小,比如你知道从1->6的权值和为15,让你求6->1的最小权重且没有负环,取一个相反数就行 了 -15 ,这就是最小的,环的为0,满足。

跑最短路spfa spfa(x) x是起点 dis数组表示x到各个点的权值,比如你输入加的边为 5 6 spfa(6) dis【5】代表6到5的权值为多少。求的是5到6,取反,答案就是-dis[5]

跑6遍spfa,每次跑完把更新完的权值加入图中。(题目保证肯定有答案,所以样例中输入的6条边的顺序 不能打乱,打乱了可能就没有答案。)

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const ll mmax=1e6;
ll n,m;
vector<ll> v1[mmax];  //二维 
vector<ll> v2[mmax];
bool isQueue[mmax];    //标记是否在队列中 
ll dis[mmax];           //某点到各个点的距离 单源最短路 
ll a[10],b[10];
void spfa(ll start)
{
	memset(dis,0x3f,sizeof(dis));
	memset(isQueue,false,sizeof(isQueue));
	dis[start]=0;    //起点距离自己为0 
	queue<ll> q;    
	q.push(start);     //起点入队 
	isQueue[start]=true;
	while(!q.empty()) 
	{
		ll u=q.front();
		q.pop();
		isQueue[u]=false;
		for(ll j=0;j<v1[u].size();j++)   
		{
			ll v=v1[u][j];   
			ll len=v2[u][j];
			if((ll)dis[u]+len<dis[v])
			{
				dis[v]=dis[u]+len;
				if(!isQueue[v])
				{
					q.push(v);
					isQueue[v]=true;
				}
			}
		}
	}
}
void init()
{
	for(int i=0;i<=mmax;i++)
	{
		v1[i].clear();
		v2[i].clear();
	}	
	memset(dis,0x3f,sizeof(dis));
	memset(isQueue,false,sizeof(isQueue));
}
int main()
{
	//ios::sync_with_stdio(false);
	ll t;
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld%lld",&n,&m);
		//memset(dis,0,sizeof(dis));
		init();
		for(int i=1;i<=m;i++)
		{
			ll x,y,t;
			scanf("%lld%lld%lld",&x,&y,&t);
			v1[x].push_back(y);
			v2[x].push_back(t);
		}
		for(ll i=1;i<=6;i++)
		{
			scanf("%lld%lld",&a[i],&b[i]);
		 } 	
		for(int i=1;i<=6;i++)
		{
			spfa(b[i]);
			ll sum=-dis[a[i]];
			v1[a[i]].push_back(b[i]); 		
			v2[a[i]].push_back(sum);
			//cout<<sum<<endl;
			printf("%lld\n",sum);
		}			
	}
	return 0;
} 
发布了88 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43667611/article/details/100187540