kuangbin最短路专题(上),还有一个下的专题

A - Til the Cows Come Home

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible. 

Farmer John's field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it. 

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.

Input

* Line 1: Two integers: T and N 

* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.

Output

* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

Hint

INPUT DETAILS: 

There are five landmarks. 

OUTPUT DETAILS: 

Bessie can get home by following trails 4, 3, 2, and 1.


//Full of love and hope for life
/*
                                                              *               ******
      *****************                                     **             *******
   ***********************                                ***                 ******
 ***************************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define inf 0x3f3f3f3f

using namespace std;

int n[2010][2010];
int a,b;
int flag[2010];
int disv[2010];

void dij()
{
    int h;
    for(int i=1;i<=b;i++)
    {
        disv[i]=n[i][1];
    }
    disv[1]=0;
    flag[1]=1;
    for(int i=1;i<b;i++)
    {
        int t=inf;
        for(int j=1;j<=b;j++)
        {
            if(flag[j]==0&&disv[j]<t)
            {
                t=disv[j];
                h=j;
            }
        }
        flag[h]=1;
        for(int k=1;k<=b;k++)
        {
            if(flag[k]==0&&disv[k]>disv[h]+n[k][h])
            {
               disv[k]=disv[h]+n[k][h];
            }
        }
    }
}

int main()
{
    int u,v,w;
    cin >> a >> b;
    for(int i=1; i<=b; i++)
    {
        for(int j=1; j<=b; j++)
        {
            if(i==j)
            {
                n[i][j]=0;
            }
            else
            {
                n[i][j]=inf;
            }
        }
    }
    for(int i=1; i<=a; i++)
    {
        cin >> u >> v >> w;
        if(n[u][v]>w)
        {
            n[u][v]=w;
            n[v][u]=w;
        }
    }
    dij();
    cout << disv[b];
    return 0;
}

B - Frogger

 

Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists' sunscreen, he wants to avoid swimming and instead reach her by jumping. 
Unfortunately Fiona's stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps. 
To execute a given sequence of jumps, a frog's jump range obviously must be at least as long as the longest jump occuring in the sequence. 
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones. 

You are given the coordinates of Freddy's stone, Fiona's stone and all other stones in the lake. Your job is to compute the frog distance between Freddy's and Fiona's stone. 

Input

The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy's stone, stone #2 is Fiona's stone, the other n-2 stones are unoccupied. There's a blank line following each test case. Input is terminated by a value of zero (0) for n.

Output

For each test case, print a line saying "Scenario #x" and a line saying "Frog Distance = y" where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.

Sample Input

2
0 0
3 4

3
17 4
19 4
18 5

0

Sample Output

Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

题意:有一只青蛙要从A点跳到B点。青蛙由于身体机能限制,所以有一个极限跳跃远度。求:这个极限最少是多少,才能完成这个任务。点是二维坐标,其中第一个点是A点,第二个点是B点。

思路:先将石头的两两距离求出来存到a里,再对最短路的松弛操作变形一下就可以了。

注:有一个坑注意一下。Put a blank line after each test case, even after the last one.每个样例后输出一个空行。

代码:
 


//Full of love and hope for life
/*
                                                              *               ******
      *****************                                     **             *******
   ***********************                                ***                 ******
 ***************************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define inf 0x3f3f3f3f

using namespace std;

double ma[210][210];
int a;
int flag[210];
double disv[210];
int n[210],m[210];

void dij()
{
    for(int i=1; i<=a; i++)
    {
        disv[i]=ma[1][i];
    }
    while(1)
    {
        int h;
        double t=inf;
        for(int j=1; j<=a; j++)
        {
            if(flag[j]==0&&disv[j]<t)
            {
                t=disv[j];
                h=j;
            }
        }
        if(t==inf)
        {
            break;
        }
        flag[h]=1;
        for(int k=1; k<=a; k++)
        {
            if(flag[k]==0&&ma[h][k]<inf&&disv[k]>max(disv[h],ma[h][k]))
            {
                disv[k]=max(disv[h],ma[h][k]);// 改变松弛条件
            }                                 // 最短路不再是路程的相加,
        }                                     //而是路程中两两的最大距离
    }
}

int main()
{
    int k=0;
    while(cin >> a)
    {
        k++;
        if(a==0)
        {
            break;
        }
        memset(flag,0,sizeof(flag));
        memset(ma,inf,sizeof(ma));
        for(int i=1; i<=a; i++)
        {
            cin >> n[i] >> m[i];
        }
        for(int i=1; i<=a; i++)// 将所有两点的距离都求出来存起来
        {
            for(int j=1; j<=a; j++)
            {
                ma[i][j]=sqrt((n[j]-n[i])*(n[j]-n[i])+(m[j]-m[i])*(m[j]-m[i]));
            }
        }
        dij();
        cout << "Scenario #" << k << endl;
        printf("Frog Distance = %.3f\n\n",disv[2]);// 每组数据后加空行
        //cout << "Frog Distance = ";
        //printf("%.3lf\n\n",disv[2]);
        //cout和printf不能混合使用,卡了14遍
    }
    return 0;
}

C - Heavy Transportation

 

Background 
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight. 
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know. 

Problem 
You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo's place) to crossing n (the customer's place). You may assume that there is at least one path. All streets can be travelled in both directions.

Input

The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.

Output

The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.

Sample Input

1
3 3
1 2 3
1 3 4
2 3 5

Sample Output

Scenario #1:
4

//Full of love and hope for life
/*
                                                              *               ******
      *****************                                     **             *******
   ***********************                                ***                 ******
 ***************************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define inf 0x3f3f3f3f

using namespace std;

int a,b;
int n[1010][1010];
int disv[1010];
int flag[1010];

void bigboom()
{
    int i,j,k;
    for(i=1; i<=b; i++)
    {
        disv[i]=n[i][1];
    }
    flag[1]=1;
    for(i=1; i<b; i++)
    {
        int g=0;
        int h;
        for(j=1; j<=b; j++)
        {
            if(flag[j]==0&&disv[j]>g)
            {
                g=disv[j];
                h=j;
            }
        }
        flag[h]=1;
        if(h==b)
        {
            break;
        }
        for(k=1; k<=b; k++)
        {
            if(flag[k]==0&&disv[k]<min(disv[h],n[k][h]))
            {
                disv[k]=min(disv[h],n[k][h]);
            }
        }
    }
    printf("%d\n\n",disv[b]);
}

int main()
{
    int T,t=0;
    scanf("%d",&T);
    while(T--)
    {
        t++;
        scanf("%d%d",&b,&a);
        memset(n,0,sizeof(n));
        memset(flag,0,sizeof(flag));
        memset(disv,0,sizeof(disv));
        int u,v,w;
        while(a--)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(n[u][v]<w)
            {
                n[u][v]=n[v][u]=w;
            }
        }
        printf("Scenario #%d:\n",t);
        bigboom();
    }
    return 0;
}

F - Wormholes

 

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W 
Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: A one way path from S to E that also moves the traveler backT seconds.

Output

Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.


//Full of love and hope for the life

//https://paste.ubuntu.com/

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define BIG  10000
typedef long long ll;
using namespace std;
const int maxn=610;
const int maxm=3000;
const int inf=0x3f3f3f3f;

int n,m,w;
struct Edge
{
    int v,nt;
    int w;
} edge[maxm*2];

int head[maxm*2];
int cnt=0;

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

int vis[maxn],tim[maxn];
int dis[maxn];

int spfa(int st)
{
    int now;
    memset(vis,0,sizeof(vis));
    memset(tim,0,sizeof(tim));
    memset(dis,inf,sizeof(dis));
    vis[st]=1;
    dis[st]=0;
    tim[st]=1;
    queue<int> q;
    q.push(st);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        vis[now]=0;
        for(int i=head[now]; i!=-1; i=edge[i].nt)
        {
            int v=edge[i].v,w=edge[i].w;
            if(dis[v]>dis[now]+w)
            {
                dis[v]=dis[now]+w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1,tim[v]++;
                    if(tim[v]>=n)
                    {
                        return 1;
                    }
                }
            }
        }
    }
    return 0;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        scanf("%d %d %d",&n,&m,&w);
        for(int i=1; i<=m; i++)
        {
            int a,b,v;
            scanf("%d %d %d",&a,&b,&v);
            add(a,b,v);
            add(b,a,v);
        }
        for(int i=1; i<=w; i++)
        {
            int a,b,v;
            scanf("%d %d %d",&a,&b,&v);
            v=v*(-1);
            add(a,b,v);
        }
        int flag=0;
        for(int i=1; i<=n; i++)
        {
            if(spfa(i))
            {
                flag=1;
                break;
            }
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}

D - Silver Cow Party(两次dij)

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: NM, and X 
Lines 2.. M+1: Line i+1 describes road i with three space-separated integers: Ai,Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.


//Full of love and hope for the life

//https://paste.ubuntu.com/

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define BIG  10000
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;

struct node
{
    int data;
    int v;
};

node g,h;
int a,b,c,ma;
int flag[2010];
int disv[2010];
int n[2010][2010];
int m[2010];

bool operator < (const node &a,const node &b)
{
    return a.data>b.data;
}

void dij(int k)
{
    priority_queue<node>q;//优化dij
    memset(disv,inf,sizeof(disv));
    memset(flag,0,sizeof(flag));
    g.data=0;
    g.v=k;
    q.push(g);
    while(!q.empty())
    {
        if(flag[q.top().v]==1)
        {
            q.pop();
            continue;
        }
        h=q.top();
        disv[h.v]=h.data;
        flag[h.v]=1;
        for(int i=1; i<=a; i++)
        {
            if(flag[i]==0&&n[h.v][i]<inf&&disv[i]>disv[h.v]+n[h.v][i])
            {
                disv[i]=disv[h.v]+n[h.v][i];
                g.v=i;
                g.data=disv[i];
                q.push(g);
            }
        }
    }
    for(int i=1; i<=a; i++)//更新路段
    {
        m[i]+=disv[i];
    }
}

int main()
{
    int u,v,w;
    cin >> a >> b >> c;
    ma=0;
    memset(n,inf,sizeof(n));
    memset(m,0,sizeof(m));
    for(int i=1; i<=a; i++)
    {
        n[i][i]=0;
    }
    for(int i=1; i<=b; i++)
    {
        cin >> u >> v >> w;
        if(n[u][v]>w)
        {
            n[u][v]=w;
        }
    }
    dij(c);
    for(int i=1; i<a; i++)
    {
        for(int j=i+1; j<=a; j++)
        {
            swap(n[i][j],n[j][i]);//返程交换路线
        }
    }
    dij(c);
    for(int i=1; i<=a; i++)
    {
        if(ma<m[i])
        {
            ma=m[i];
        }
    }
    cout << ma << endl;
    return 0;
}

E - Currency Exchange

 

Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency. 
For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR. 
You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges, and real R AB, C AB, R BA and C BA - exchange rates and commissions when exchanging A to B and B to A respectively. 
Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative sum of money while making his operations. 

Input

The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain 6 numbers each - the description of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=10 3. 
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10 -2<=rate<=10 2, 0<=commission<=10 2. 
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 10 4. 

Output

If Nick can increase his wealth, output YES, in other case output NO to the output file.

Sample Input

3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output

YES

题意:有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加 货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的 怎么找正权回路呢?

思路:Bellman-Ford算法能找到负回路,所以只要改变松弛条件就可以找到正回路。

代码:
 


//Full of love and hope for life

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
//https://paste.ubuntu.com/

using namespace std;

int flag[1010];
double n[1010][1010];// rate[3][5]=7.2 >> 3到5的利率为7.2
double m[1010][1010];// 手续费
double disv[1010];// 钱数
int a,b,s,a1,b1;
double now,x,y,z,w;

int bellman_ford(int h){// 经典的bellman_ford算法
    double t;
    int g;
    memset(disv,0,sizeof(disv));
    disv[h]=now;
    for(int i=1;i<=a;i++){
        g=0;
        for(int j=1;j<=a;j++){
            for(int k=1;k<=a;k++){
                t=(disv[j]-m[j][k])*n[j][k]; // 从j到k剩余的钱
                if(t>disv[k]){// 如果从j到k 大于 原本k的钱那么松弛
                    disv[k]=t;
                    g=1;
                }
            }
        }
        if(g==0){
            return 0;
        }
    }
    for(int j=1;j<=a;j++){
        for(int k=1;k<=a;k++){
            t=(disv[j]-m[j][k])*n[j][k];
            if(t>disv[k]){
                    disv[k]=t;
                    g=1;
            }
        }
    }
    return g;
}

int main(){
    cin >> a >> b >> s >> now;
    memset(n,0,sizeof(n));
    memset(m,0,sizeof(m));
    for(int i=1;i<=b;i++){
        cin >> a1 >> b1;
        cin >> x >> y;
        cin >> z >> w;
        n[a1][b1]=x;
        n[b1][a1]=z;
        m[a1][b1]=y;
        m[b1][a1]=w;
    }
    int ans=bellman_ford(s);
    if(ans){
        cout << "YES";
    }
    else{
        cout << "NO";
    }
    return 0;
}

G - MPI Maelstrom

 

BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee's research advisor, Jack Swigert, has asked her to benchmark the new system. 
``Since the Apollo is a distributed shared memory machine, memory access and communication times are not uniform,'' Valentine told Swigert. ``Communication is fast between processors that share the same memory subsystem, but it is slower between processors that are not on the same subsystem. Communication between the Apollo and machines in our lab is slower yet.'' 

``How is Apollo's port of the Message Passing Interface (MPI) working out?'' Swigert asked. 

``Not so well,'' Valentine replied. ``To do a broadcast of a message from one processor to all the other n-1 processors, they just do a sequence of n-1 sends. That really serializes things and kills the performance.'' 

``Is there anything you can do to fix that?'' 

``Yes,'' smiled Valentine. ``There is. Once the first processor has sent the message to another, those two can then send messages to two other hosts at the same time. Then there will be four hosts that can send, and so on.'' 

``Ah, so you can do the broadcast as a binary tree!'' 

``Not really a binary tree -- there are some particular features of our network that we should exploit. The interface cards we have allow each processor to simultaneously send messages to any number of the other processors connected to it. However, the messages don't necessarily arrive at the destinations at the same time -- there is a communication cost involved. In general, we need to take into account the communication costs for each link in our network topologies and plan accordingly to minimize the total time required to do a broadcast.''

Input

The input will describe the topology of a network connecting n processors. The first line of the input will be n, the number of processors, such that 1 <= n <= 100. 

The rest of the input defines an adjacency matrix, A. The adjacency matrix is square and of size n x n. Each of its entries will be either an integer or the character x. The value of A(i,j) indicates the expense of sending a message directly from node i to node j. A value of x for A(i,j) indicates that a message cannot be sent directly from node i to node j. 

Note that for a node to send a message to itself does not require network communication, so A(i,i) = 0 for 1 <= i <= n. Also, you may assume that the network is undirected (messages can go in either direction with equal overhead), so that A(i,j) = A(j,i). Thus only the entries on the (strictly) lower triangular portion of A will be supplied. 

The input to your program will be the lower triangular section of A. That is, the second line of input will contain one entry, A(2,1). The next line will contain two entries, A(3,1) and A(3,2), and so on.

Output

Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.

Sample Input

5
50
30 5
100 20 50
10 x x 10

Sample Output

35

题意:前面一大段都是废话,其实只看input和output也能大体看懂。N个处理器要进行信息传递,处理器i传递信息给自己不需要时间,处理器i与处理器j之间相互传递信息的时间是一样的,不同处理器之间传递信息所需要的时间由一个矩阵的下三角给出。若矩阵对应位置为x,则说明相应的两个处理器之间无法传递信息。求从第一个处理器传递信息到其他所有处理器最少需要多少时间。

思路:Dijkstra算法,最后求1到其他点dis的最大值输出。

注:其中用到了比较方便的atoi函数:https://blog.csdn.net/weixin_43828245/article/details/91356193

代码:
 


//Full of love and hope for life

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

struct node{
int data;
int v;
};

int flag[1000];
int disv[1000];
char s[55];
int n[1000][1000];
int a;
node g,h;

bool operator < (const node &a,const node &b){
    return a.data>b.data;
}

void dij(){
    priority_queue<node>q;
    g.data=0;
    g.v=1;
    q.push(g);
    while(!q.empty()){
        if(flag[q.top().v]==1){
            q.pop();
            continue;
        }
        h=q.top();
        flag[h.v]=1;
        disv[h.v]=h.data;
        for(int i=1;i<=a;i++){
            if(flag[i]==0&&n[h.v][i]<inf&&disv[i]>disv[h.v]+n[h.v][i]){
                disv[i]=disv[h.v]+n[h.v][i];
                g.v=i;
                g.data=disv[i];
                q.push(g);
            }
        }
    }
    int ma=0;
    for(int i=1;i<=a;i++){
        if(ma<disv[i]){
            ma=disv[i];
        }
    }
    cout << ma;
}

int main(){
    cin >> a;
    memset(flag,0,sizeof(flag));
    memset(disv,inf,sizeof(disv));
    memset(n,inf,sizeof(n));
    for(int i=1;i<=a;i++){
        n[i][i]=0;
    }
    for(int i=2;i<=a;i++){
        for(int j=1;j<i;j++){
            cin >> s;
            if(s[0]=='x'){
                n[i][j]=n[j][i]=inf;
            }
            else{
                n[i][j]=n[j][i]=atoi(s);
            }
        }
    }
    dij();
    return 0;
}

H - Cow Contest

 

N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ A ≤ N; 1 ≤ B ≤ NA ≠ B), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the results of M(1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and B

Output

* Line 1: A single integer representing the number of cows whose ranks can be determined
 

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

题意:有N头牛,评以N个等级,各不相同,先给出部分牛的等级的高低关系,问最多能确定多少头牛的等级。

思路:现将已知两头牛的关系按照单向图存入a,通过Floyd把传递关系弄出来。现在当一个点的出度+入度和等于n-1(即和他和所有的点都直接或间接的确定了关系),那么他的关系就确定了。

代码:
 


//Full of love and hope for life

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

int a,b;
int n[110][110];

void ford(){
    for(int i=1;i<=a;i++){
        for(int j=1;j<=a;j++){
           for(int k=1;k<=a;k++){
               if(n[j][i]==1&&n[i][k]==1){// 做出传递关系
                   n[j][k]=1;
               }
           }
        }
    }
}

int main(){
    int x,y,ans;
    ans=0;
    cin >> a >> b;
    memset(n,0,sizeof(n));
    while(b--){
        cin >> x >> y;
        n[x][y]=1;
    }
    ford();
    for(int i=1;i<=a;i++){
            int t=1;
        for(int j=1;j<=a;j++){
            if(i!=j&&n[i][j]==0&&n[j][i]==0){// 当出度=0入度=0,
                t=0; //       还不是自己和自己,那么不是确定关系的点
                break;
            }
        }
    if(t==1){
        ans++;
    }
    }
    cout << ans;
    return 0;
}

I - Arbitrage

 

Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent. 

Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not. 

Input

The input will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible. 
Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n.

Output

For each test case, print one line telling whether arbitrage is possible or not in the format "Case case: Yes" respectively "Case case: No".

Sample Input

3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar

3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar

0

Sample Output

Case 1: Yes
Case 2: No

题意:已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加。

思路:这里给的顶点时货币的英文名,为了方便简洁,用map 将货币名 与 编号一一对应。反向使用bellman_ford 判断是否存在正回路(存在正回路,财富增加)。

注: 用string类,必须#include ,引用cstring没用。使用map引用#include和#include

代码:
 


//Full of love and hope for life

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

int a,b;
double n[110][110];// j到k的汇率
double disv[110];// 每个节点的钱数

int ford(){// 反向使用bellman,找正回路
    memset(disv,0,sizeof(disv));// 全部设成0,方便往大了松弛
    disv[1]=1;
    for(int i=1;i<=a;i++){
            int f=0;
        for(int j=1;j<=a;j++){
            for(int k=1;k<=a;k++){
                double t=disv[j]*n[j][k]; // 这个很巧妙
            if(t>disv[k]){
                disv[k]=t;// 往大了松弛
                f=1;
            }
            }
        }
        if(f==0)
        {
            return 0;
        }
    }
    int f=0;
    for(int j=1;j<=a;j++){
        for(int k=1;k<=a;k++){
            double t=disv[j]*n[j][k];
        if(t>disv[k]){
            disv[k]=t;
            f=1;
           }
        }
    }
    return f;
}

int main() {
    int k=0;
    string s,ss;
    double c;
    while(cin >> a&&a){
       k++;
       map<string,int>m;// 将字符串转抽象成数字
       memset(n,0,sizeof(n));
       for(int i=1;i<=a;i++){
           cin >> s;
           m[s]=i;
       }
       cin >> b;
       for(int i=1;i<=b;i++){
           cin >> s >> c >> ss;
           n[m[s]][m[ss]]=c;
       }
       int t=ford();
       cout << "Case " << k << ": ";
       if(t==1){
           cout << "Yes" << endl;
       }
       else{
           cout << "No" << endl;
       }
       }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
并查集是一种常用的数据结构,用于管理一个不相交集合的数据。在并查集中,每个元素都有一个父节点指向它所属的集合的代表元素。通过查找和合并操作,可以判断两个元素是否属于同一个集合,并将它们合并到同一个集合中。 在解决某些问题时,可以使用并查集进行优化。例如,在区间查询中,可以通过优化并查集的查询过程,快速找到第一个符合条件的点。 对于拆边(destroy)操作,一般的并查集无法直接实现这个功能。但是可以通过一个巧妙的方法来解决。首先,记录下所有不会被拆除的边,然后按照逆序处理这些指令。遇到拆边操作时,将该边重新加入并查集中即可。 在实现并查集时,虽然它是一种树形结构,但只需要使用数组就可以实现。可以通过将每个元素的父节点记录在数组中,来表示元素之间的关系。通过路径压缩和按秩合并等优化策略,可以提高并查集的效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [「kuangbin带你飞」专题五并查集专题题解](https://blog.csdn.net/weixin_51216553/article/details/121643742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [并查集(详细解释+完整C语言代码)](https://blog.csdn.net/weixin_54186646/article/details/124477838)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZ --瑞 hopeACMer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值