Week7 homework-C-TT's dream

topic

This night, TT had a sweet dream!

In the dream, TT's wish came true, and he became the leader of the cat! There are N commercial cities on Meow Star, numbered from 1 to N, of which city 1 is the city where TT is located, that is, the capital.

There are a total of M directed roads on Meow Star for commercial cities to travel between. But with the growing prosperity of the cat business, some roads have become very crowded. While TT was distressed, his magic kitty came up with a solution! TT gladly accepted and promulgated a new policy for this plan.

The specific policy is as follows: Mark a positive integer for each commercial city to indicate its degree of prosperity. When each cat walks from one commercial city to another along the road, TT will charge them (Destination Prosperity-Departure) Prosperity) ^ 3 tax.

TT intends to test whether this policy is reasonable, so he wants to know how much tax should be paid at least to go to other cities from the capital. If the total amount is less than 3 or cannot be reached, please quietly type'?'.

Input

Enter T in the first line, indicating that there are T groups of data. (1 <= T <= 50)

For each group of data, enter N in the first line, which indicates the number of points. (1 <= N <= 200)

Enter N integers in the second line, representing the weight a[i] of 1 to N points. (0 <= a[i] <= 20)

Enter M in the third line to indicate the number of directed roads. (0 <= M <= 100000)

In the next M lines, each line has two integers AB, indicating that there is a directed road from A to B.

Next, an integer Q is given, which represents the number of queries. (0 <= Q <= 100000)

Each inquiry gives a P, which means finding the minimum tax from point 1 to point P.

Output

Output one line for each query, and output'?' if it is unreachable or tax is less than 3.

Sample Input

2
5
6 7 8 9 10
6
1 2
2 3
3 4
1 5
5 4
4 5
2
4
5
10
1 2 4 4 5 6 7 8 9 10
10
1 2
2 3
3 1
1 4
4 5
5 6
6 7
7 8
8 9
9 10
2
3 10

Sample Output

Case 1:
3
4
Case 2:
?
?

Negative weight loop

How to judge the existence of negative ring in Bellman-ford algorithm? • If there is a negative ring, then the number of edges passed by the shortest path will be greater than or equal to n.
• Some edges will be relaxed greater than or equal to n.
• If there are still edges that can be successfully relaxed during the nth relaxation operation, then there is a negative The ring
Insert picture description here
SPFA algorithm is a queue optimization of the Bellman-ford algorithm. The judgment condition for the existence of a negative ring is the same as that of the Bellman-ford algorithm. Thinking: How to judge that the number of times an edge is relaxed is greater than or equal to n?

• In SPFA, adding a point to the queue, it is not easy to judge the slack times of the edge.
• The condition can be relaxed to judge the number of times the point has been enqueued. If a point has entered the queue n times, it means there is a negative ring
. The number of edges of the shortest path at a certain point exceeds n-1, it means there is a negative ring (used in this question). The
modified SPFA algorithm
• cnt[x] represents the number of edges on the current shortest path of x
• Lines 16 and 17 are recorded The shortest path length of v cnt[v], and then judge that cnt[v] is greater than or equal to n, it means that a negative ring has been found.
Insert picture description here

Ideas

The problem requires starting from 1 to other points and spending the least money, which is equivalent to finding the shortest path from 1 to other points.
• It is worth noting that after a road, the tax collected by TT may be negative.
• There are negative weighted edges in the graph. This is a single-source shortest path problem with negative weighted edges.
Under what circumstances will output'?' • Unreachable • The shortest path is less than 3 • The shortest path exists • The shortest path does not exist
• Need We judge the negative ring. The shortest paths of the points that can be reached through the negative ring do not exist
. After finding the negative ring, mark the points in the connected block where the negative ring is located.

1. Use the chain forward star to save the picture
2. Call the spfa algorithm, first put 1 into the queue, and set inq[1]=1, dis[1]=0
3. Enter the queue before continuously taking it out from the head of the queue Point, set inq[x] to 0, traverse the directed edges emitted by this point, and judge whether these directed edges can be used to update the distance of the other end (considering that the shortest path of length 3 can only be length 2 If the shortest path of length 1 plus an edge is formed, the shortest path of length 2 will inevitably be updated when the shortest path of length 2 is updated, so when you want to get the length of i For the shortest path, only the nodes updated in the shortest path of the update length i-1 can be considered. Therefore, each time the node of the shortest path of a length is updated, the newly updated node is put into the queue, and in the update For the next length, you only need to extend an edge from these nodes to update). When it can be updated, update the array cnt of the shortest path length to that point at the same time, and judge whether cnt[y]>=n, if>= n, call dfs(y), and mark the fu of all points reachable by y as 1.
4. Determine whether the new endpoint taken out in 3 is already in the stack and is not a vertex reachable by the negative ring, and when the conditions are met, add the point to the queue.

error

An error occurred as a comment in the code

Code

#include<iostream>
#include<queue>
#include<cmath>
#include<string.h>
using namespace std;
const int maxn=201;
const int maxm=100010;
const int INF=0x3f3f3f3f;
struct edge
{
    
    
 int to,next,w; 
}e[maxm];
int n,a[maxn],head[maxn],tot,dis[maxn],cnt[maxn];
bool inq[maxn],fu[maxn];
queue<int> que;
void add(int x,int y,int w)
{
    
    
 e[++tot].to=y;
 e[tot].next=head[x];
 e[tot].w=w;
 head[x]=tot;
}
void dfs(int x)
{
    
    
 fu[x]=1; 
 for(int i=head[x];i;i=e[i].next)
 {
    
    
  int y=e[i].to;
  if(!fu[y])
  {
    
    
   fu[y]=1;
   dfs(y);
  }
 }
}
void spfa(int s)
{
    
    
 while(que.size())
  que.pop();
 for(int i=1;i<=n;i++)
 {
    
    
  inq[i]=0;
  cnt[i]=0;
  dis[i]=INF;
  fu[i]=0;
 }
 dis[s]=0;
 inq[s]=1;
 que.push(s);
 while(!que.empty())
 {
    
    
  int x=que.front();
  que.pop();
  inq[x]=0;
  for(int i=head[x];i;i=e[i].next)
  {
    
    
   int y=e[i].to;
   if(dis[y]>dis[x]+e[i].w)
   {
    
    
    dis[y]=dis[x]+e[i].w;
    cnt[y]=cnt[x]+1;
    if(cnt[y]>=n)
    {
    
    
     dfs(y);
    }
    if(!inq[y]&&!fu[y])
    {
    
    
     inq[y]=1;
     que.push(y);
    }
   }
  }
 }
}
int main()
{
    
    
 int t,m,A,B,q,p;
 scanf("%d",&t);
 for(int i=0;i<t;i++)
 {
    
    
  tot=1;
  memset(head,0,sizeof(head));//将head清空要在录入边之前。 
  scanf("%d",&n);
  for(int j=1;j<=n;j++)
   scanf("%d",&a[j]);
  scanf("%d",&m);
  for(int j=0;j<m;j++)
  {
    
    
   scanf("%d%d",&A,&B);
   int w=pow((a[B]-a[A]),3);
   add(A,B,w);
  }
  spfa(1);
  scanf("%d",&q);
  printf("Case %d:\n",i+1);//注意输出格式 
  for(int j=0;j<q;j++)
  {
    
    
   scanf("%d",&p);
   if(dis[p]==INF||dis[p]<3||fu[p]==1)
    printf("?\n");
   else
   {
    
    
    printf("%d\n",dis[p]);
   }
  }
 }
 return 0;
}

Guess you like

Origin blog.csdn.net/alicemh/article/details/105288799