2019ACM南京網絡賽 Holy Grail

題目鏈接: https://nanti.jisuanke.com/t/41305

SPFA 或 Bellman-Ford模板題(存在負權路徑)

Description

1000ms 262144K

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 :

1 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).
2 May have negative-weighted edges.
3 Does not have a negative-weighted loop.
4 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:

1 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).
2 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

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 x, y and w (0≤x,y<n,−109-109≤w≤109, 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 6 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

使用鏈式前向星存圖+SPFA尋找單源最短路徑
一開始沒有讀懂題,畫了樣例的圖感覺是最短路的負數,直接試了一下SPFA模板AC了
記得每次詢問之後要把詢問的邊添加到圖中

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int const INF = 0x3f3f3f3f;
int const maxn = 1005;

int dis[maxn];
int head[maxn];
int n, m, cnt;
bool vis[maxn];

struct NODE
{
    int v, w, next;
} edge[100005];

void AddEdge(int u, int v, int w)
{
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

void SPFA(int s)
{
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;

    queue<int>que;
    que.push(s);
    while(que.size())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;

        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            int w = edge[i].w;
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.push(v);
                }
            }
        }
    }
}

int main()
{
    int T, u, v, w;

    scanf("%d", &T);
    while(T--)
    {
        cnt = 0;
        memset(head, -1, sizeof(head));

        scanf("%d %d", &n, &m);
        while(m--)//建圖
        {
            scanf("%d %d %d", &u, &v, &w);
            AddEdge(u, v, w);
        }

        for(int i = 0; i < 6; i++)
        {
            scanf("%d%d", &u, &v);
            SPFA(v);
            AddEdge(u, v, -dis[u]);//每次查詢完要將邊添加到圖中
            printf("%d\n", -dis[u]);//輸出最短路徑的負值
        }
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章