PAT class a graph theory

Keywords: C C++ Algorithm

Test site

1. Various deformations of Dijkstra
2. Connectivity, judging the number of connected blocks
3. Hierarchical traversal
4. Ergodic properties of edges

Foundation preparation - Dijkstra I

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510;

int n, m;
int g[N][N];
int dist[N];
bool st[N];

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    for (int i = 0; i < n - 1; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);

        st[t] = true;
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    memset(g, 0x3f, sizeof g);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);

        g[a][b] = min(g[a][b], c);
    }

    printf("%d\n", dijkstra());

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/308477/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Basics - Dijkstra II

#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 1e6 + 10;

int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.second, distance = t.first;

        if (st[ver]) continue;
        st[ver] = true;

        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }

    cout << dijkstra() << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/308478/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

emergency

Class a 1003

subject

As the head of the city's emergency rescue team, you will get a special map of your country.

The map shows some scattered cities connected by roads, which are two-way.

The map shows the number of rescue teams in each city and the length of each road between each pair of cities.

When other cities send out emergency messages for help, your job is to lead your soldiers to the location as soon as possible, and mobilize as many rescue helpers as possible on the way.

Input format
The first line contains four integers N, which indicates the number of cities (city number from 0 to N − 1), M indicates the number of roads, C1 indicates the number of your current city, and C2 indicates the number of the city that sent the emergency help message.

The second line contains N integers, where the ith integer represents the number of rescue teams in city i.

Next, line M contains three integers c1, c2 and Li, indicating that there is a road between city c1 and city c2, and the road length is Li.

The data ensures that there is at least one path between C1 and C2.

Output format
There are two integers in a row. The first integer represents the number of the shortest circuit between C1 and C2, and the second integer represents the maximum number of rescue teams that can be gathered in the case of the shortest circuit.

Data range
2≤N≤500,
1≤M≤600,
1≤Li≤200,
Each city contains no more than 200 rescue workers.

Input example:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Output example:
2 4

thought

It can be found that this problem is a deformation of Dijkstra,
In the case of finding the shortest path, solve the case with the most rescuers—— sum
And count the number of shortest circuits - cnt[j]

Save involving shortest path

        for(j = 0; j < n; j ++){
            if(dist[j] > dist[t] + d[t][j]){
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                sum[j] = sum[t] + w[j];
            }
            else if(dist[j] == dist[t] + d[t][j]){
                cnt[j] += cnt[t];
                sum[j] = max(sum[j], sum[t] + w[j]);
            }
        }

My code

#include <iostream>
#include <cstring>
using namespace std;
const int N = 510;
int n, m, c1, c2;
int cnt[N], sum[N], w[N], d[N][N], dist[N];
bool st[N];
void dijkstra(){
    int i, j;
    memset(dist, 0x3f, sizeof dist);
    dist[c1] = 0, cnt[c1] = 1, sum[c1] = w[c1];
    for(i = 0; i < n; i ++){
        int t = -1;
        for(j = 0; j < n; j ++){
            if(!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;
        }
        st[t] = true;
        for(j = 0; j < n; j ++){
            if(dist[j] > dist[t] + d[t][j]){
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                sum[j] = sum[t] + w[j];
            }
            else if(dist[j] == dist[t] + d[t][j]){
                cnt[j] += cnt[t];
                sum[j] = max(sum[j], sum[t] + w[j]);
            }
        }
    }
}


int main(){
    cin>>n>>m>>c1>>c2;
    for (int i = 0; i < n; i ++ ) cin >> w[i];

    memset(d, 0x3f, sizeof d);
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = d[b][a] = min(d[a][b], c);
    }
    
    dijkstra();
    cout<<cnt[c2]<<" "<<sum[c2]<<endl;
}

y total code

#include <cstring>
#include <iostream>

using namespace std;

const int N = 510;

int n, m, S, T;
int w[N], d[N][N];
int dist[N], cnt[N], sum[N];
bool st[N];

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[S] = 0, cnt[S] = 1, sum[S] = w[S];

    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 0; j < n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;

        for (int j = 0; j < n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                sum[j] = sum[t] + w[j];
            }
            else if (dist[j] == dist[t] + d[t][j])
            {
                cnt[j] += cnt[t];
                sum[j] = max(sum[j], sum[t] + w[j]);
            }
    }
}

int main()
{
    cin >> n >> m >> S >> T;

    for (int i = 0; i < n; i ++ ) cin >> w[i];

    memset(d, 0x3f, sizeof d);
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = d[b][a] = min(d[a][b], c);
    }

    dijkstra();

    cout << cnt[T] << ' ' << sum[T] << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/294255/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Travel plan

Class a 1030

subject

Given a map, including N cities and M expressways.

Cities can be interconnected.

The length of each highway and the cost of taking the highway are known. Highways are two-way.

Now go from one city on the map to another.

Please determine the shortest path. When the shortest path is not unique, please select the path with the least cost (ensure uniqueness).

Input format
The first line contains four integers n, m, s and D, which respectively represent the number of cities, the number of roads, the starting city number and the ending city number.

City numbers range from 0 to N − 1.

Next, line M contains four integers a, b, c and d, indicating that there is a highway between city a and city b, with a length of c and a cost of d.

Output format
In one line, first output all cities passed by the shortest path (with the least cost) from the starting city to the ending City, and then output the distance of the shortest path and the minimum cost.

Data range
1≤N≤500,
1≤M≤600,
1≤c,d≤500
Input example:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Output example:
0 2 3 3 40

thought

This problem is still a deformation of Dijkstra
It requires the least cost in all schemes for finding the shortest path,
And record the path

Insert the code slice here

My code

        for (int j = 0; j < n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cost[j] = cost[t] + c[t][j];
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j] && cost[j] > cost[t] + c[t][j])
            {
                cost[j] = cost[t] + c[t][j];
                pre[j] = t;
            }
    }

y total code

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

const int N = 510;

int n, m, S, T;
int d[N][N], c[N][N];
int dist[N], cost[N], pre[N];
bool st[N];

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    memset(cost, 0x3f, sizeof cost);

    dist[S] = 0, cost[S] = 0;
    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 0; j < n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;

        for (int j = 0; j < n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cost[j] = cost[t] + c[t][j];
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j] && cost[j] > cost[t] + c[t][j])
            {
                cost[j] = cost[t] + c[t][j];
                pre[j] = t;
            }
    }
}

int main()
{
    cin >> n >> m >> S >> T;
    memset(d, 0x3f, sizeof d);
    memset(c, 0x3f, sizeof c);

    while (m -- )
    {
        int a, b, x, y;
        cin >> a >> b >> x >> y;
        if (x < d[a][b])
        {
            d[a][b] = d[b][a] = x;
            c[a][b] = c[b][a] = y;
        }
        else if (x == d[a][b] && y < c[a][b])
        {
            c[a][b] = c[b][a] = y;
        }
    }

    dijkstra();

    vector<int> path;
    for (int i = T; i != S; i = pre[i]) path.push_back(i);

    cout << S;
    for (int i = path.size() - 1; i >= 0; i -- ) cout << ' ' << path[i];
    cout << ' ' << dist[T] << ' ' << cost[T] << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/294264/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Gang leader

subject

One way for the police to find the gang leader is to check people's calls.

If there is A call between A and B, we say A and B are related. And the association is transitive, that is, if A is associated with B and B is associated with C, then A and C are also associated.

The association weight is defined as the total length of all calls between two people.

A "Gang" is a group composed of at least three interrelated people, and its total association weight is greater than the given threshold K.

In each gang, the leader with the largest total weight is the leader. The data ensure that the person with the largest total weight in each gang is the only one.

You need to identify each gang and gang leader.

Input format
The first line contains two integers N and K, indicating the number of calls and the weight threshold.

Next, there are N lines. Each line describes the call in the following form:

Name1 Name2 Time
Name1 and Name2 are the names of the two people talking, and Time is the talk Time.

The length of the name is fixed to 3 and contains only uppercase letters.

Time is a positive integer no more than 1000.

Output format
The first line outputs the number of gangs.

Next, each line outputs the information of a gang, including the name of the gang leader and the number of gang members.

The gang information is output in the order of the leader's name dictionary.

Data range
1≤N,K≤1000
Input example 1:
8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Output example 1:
2
AAA 3
GGG 3
Input example 2:
8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Output example 2:
0

thought

(1) Find the connected block, and find the total weight of the connected block

int dfs(string u, vector<string> &node){//To return the total weight and nodes, you cannot only return the number of nodes, because you need to judge the node with the largest weight
    st[u] = true;
    node.push_back(u);
    int sum = 0;
    for(auto edge : g[u]){
        sum += edge.second;
        string cur = edge.first;
        if(!st[cur]) sum += dfs(cur, node);//Only those that have not been traversed can be added
    }
    return sum;
}

My code

//Topic test site 1: judge Unicom block - deep search or and set search
//Topic test site 2: find the node with the largest weight in the Unicom block - you need to record which nodes are in the Unicom block, and then traverse to find the largest
//Topic test site 3: storage diagram - unordered_map; Record weight - total
//Topic test site 4: output needs sorting
#include<iostream>
#include <unordered_map>
#include <algorithm>
#include <vector>
using namespace std;
unordered_map<string, vector<pair<string, int>>> g;
unordered_map<string, int> total;//According to the title, I need a to store the total weight of different points
unordered_map<string, bool> st;
int dfs(string u, vector<string> &node){//To return the total weight and nodes, you cannot only return the number of nodes, because you need to judge the node with the largest weight
    st[u] = true;
    node.push_back(u);
    int sum = 0;
    for(auto edge : g[u]){
        sum += edge.second;
        string cur = edge.first;
        if(!st[cur]) sum += dfs(cur, node);//Only those that have not been traversed can be added
    }
    return sum;
}
int main(){
    int n, k, i;
    cin>>n>>k;
    for(i = 0; i < n; i ++){
        string a, b;
        int w;
        cin>>a>>b>>w;
        g[a].push_back({b, w});
        g[b].push_back({a, w});
        total[a] += w;
        total[b] += w;
    }
    vector<pair<string, int>> res;
    for(auto item : total){
        string ver = item.first;
        vector<string> node;
        int sum = dfs(ver, node) / 2;
        if(node.size() > 2 && sum > k){
            string boss;
            int tot = -1;
            for(auto no : node){
                if(total[no] > tot){
                    boss = no;
                    tot = total[no];
                }
            }
            res.push_back({boss, node.size()});
        }
    }
    sort(res.begin(), res.end());
    cout<<res.size()<<endl;
    for(auto re : res){
        cout<<re.first<<" "<<re.second<<endl;
    }
    
}

y total code

#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

using namespace std;

int n, k;
unordered_map<string, vector<pair<string, int>>> g;
unordered_map<string, int> total;
unordered_map<string, bool> st;

int dfs(string ver, vector<string> &nodes)
{
    st[ver] = true;
    nodes.push_back(ver);

    int sum = 0;
    for (auto edge : g[ver])
    {
        sum += edge.second;
        string cur = edge.first;
        if (!st[cur]) sum += dfs(cur, nodes);
    }

    return sum;
}

int main()
{
    cin >> n >> k;
    while (n -- )
    {
        string a, b;
        int t;
        cin >> a >> b >> t;
        g[a].push_back({b, t});
        g[b].push_back({a, t});
        total[a] += t;
        total[b] += t;
    }

    vector<pair<string, int>> res;
    for (auto item : total)
    {
        string ver = item.first;
        vector<string> nodes;
        int sum = dfs(ver, nodes) / 2;

        if (nodes.size() > 2 && sum > k)
        {
            string boss = nodes[0];
            for (string node : nodes)
                if (total[boss] < total[node])
                    boss = node;
            res.push_back({boss, (int)nodes.size()});
        }
    }

    sort(res.begin(), res.end());

    cout << res.size() << endl;
    for (auto item : res) cout << item.first << ' ' << item.second << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/294285/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

All roads lead to Rome

Class a 1087

subject

There are many different tourist routes from our city to Rome.

Please find the route that makes tourists feel the most happy among the tourist routes with the lowest cost.

Input format
The first line contains two integers N and K, which respectively represent the total number of cities and the number of roads between cities. It also contains a city name, which represents the initial city.

The next N − 1 line contains a city name and an integer, indicating the happiness you can get when you arrive in the city (except the initial city).

Next, line K, each line contains the information of a road in the format of City1 City2 Cost, indicating the cost of walking the road between the two cities. The road is two-way.

Cities are strings of three capital letters.

Our destination has always been Rome.

Output format
We should find the lowest cost route.

If this route is not the only one, choose the route that makes people get the greatest happiness.

If this route is still not unique, then we choose the route with the greatest average happiness, and the data ensure that this route is unique.

Average well-being = total well-being / number of cities passed (excluding initial cities)

The first line outputs four integers, the number of routes with minimum cost, minimum cost, well-being and average well-being (only the integer part is taken).

In the second line, output the route in the format of city1 - > city2 - >... - > ROM.

Data range
2≤N≤200,
1≤K≤250,
The happiness of each city ranges from [0100],
The maximum cost per route shall not exceed 1000
Input example:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
Output example:
3 3 195 97
HZH->PRS->ROM

thought

Record the number of minimum cost paths, maximum happiness, average happiness - number of cities

for (int j = 1; j <= n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                cost[j] = cost[t] + w[j];
                sum[j] = sum[t] + 1;
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j])
            {
                cnt[j] += cnt[t];
                if (cost[j] < cost[t] + w[j])
                {
                    cost[j] = cost[t] + w[j];
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
                else if (cost[j] == cost[t] + w[j])
                {
                    if (sum[j] > sum[t] + 1)
                    {
                        sum[j] = sum[t] + 1;
                        pre[j] = t;
                    }
                }
            }

My code

//Convert the city string into numbers, which is convenient for algorithm writing!!!

#include <iostream>
#include <cstring>
#include <unordered_map>
#include <vector>

using namespace std;

const int N = 210;

int n, m;
int w[N];
int d[N][N];
int dist[N], cnt[N], cost[N], sum[N], pre[N];
// The shortest distance, the number of shortest paths, the maximum point weight, the minimum number of points, and the previous point of the shortest path
bool st[N];

string city[N];
unordered_map<string, int> mp;

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0, cnt[1] = 1;

    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;

        for (int j = 1; j <= n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                cost[j] = cost[t] + w[j];
                sum[j] = sum[t] + 1;
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j])
            {
                cnt[j] += cnt[t];
                if (cost[j] < cost[t] + w[j])
                {
                    cost[j] = cost[t] + w[j];
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
                else if (cost[j] == cost[t] + w[j])
                {
                    if (sum[j] > sum[t] + 1)
                    {
                        sum[j] = sum[t] + 1;
                        pre[j] = t;
                    }
                }
            }
    }
}

int main()
{
    cin >> n >> m >> city[1];
    mp[city[1]] = 1;

    for (int i = 2; i <= n; i ++ )
    {
        cin >> city[i] >> w[i];
        mp[city[i]] = i;
    }

    memset(d, 0x3f, sizeof d);
    while (m -- )
    {
        string x, y;
        int c;
        cin >> x >> y >> c;
        int a = mp[x], b = mp[y];
        d[a][b] = d[b][a] = min(d[a][b], c);
    }

    dijkstra();

    int T = mp["ROM"];
    cout << cnt[T] << ' ' << dist[T] << ' ' << cost[T] << ' ' << cost[T] / sum[T] << endl;

    vector<int> path;
    for (int i = T; i != 1; i = pre[i]) path.push_back(i);

    cout << city[1];
    for (int i = path.size() - 1; i >= 0; i -- )
        cout << "->" << city[path[i]];
    cout << endl;

    return 0;
}

y total code

#include <iostream>
#include <cstring>
#include <unordered_map>
#include <vector>

using namespace std;

const int N = 210;

int n, m;
int w[N];
int d[N][N];
int dist[N], cnt[N], cost[N], sum[N], pre[N];
// The shortest distance, the number of shortest paths, the maximum point weight, the minimum number of points, and the previous point of the shortest path
bool st[N];

string city[N];
unordered_map<string, int> mp;

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0, cnt[1] = 1;

    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;

        for (int j = 1; j <= n; j ++ )
            if (dist[j] > dist[t] + d[t][j])
            {
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                cost[j] = cost[t] + w[j];
                sum[j] = sum[t] + 1;
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j])
            {
                cnt[j] += cnt[t];
                if (cost[j] < cost[t] + w[j])
                {
                    cost[j] = cost[t] + w[j];
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
                else if (cost[j] == cost[t] + w[j])
                {
                    if (sum[j] > sum[t] + 1)
                    {
                        sum[j] = sum[t] + 1;
                        pre[j] = t;
                    }
                }
            }
    }
}

int main()
{
    cin >> n >> m >> city[1];
    mp[city[1]] = 1;

    for (int i = 2; i <= n; i ++ )
    {
        cin >> city[i] >> w[i];
        mp[city[i]] = i;
    }

    memset(d, 0x3f, sizeof d);
    while (m -- )
    {
        string x, y;
        int c;
        cin >> x >> y >> c;
        int a = mp[x], b = mp[y];
        d[a][b] = d[b][a] = min(d[a][b], c);
    }

    dijkstra();

    int T = mp["ROM"];
    cout << cnt[T] << ' ' << dist[T] << ' ' << cost[T] << ' ' << cost[T] / sum[T] << endl;

    vector<int> path;
    for (int i = T; i != 1; i = pre[i]) path.push_back(i);

    cout << city[1];
    for (int i = path.size() - 1; i >= 0; i -- )
        cout << "->" << city[path[i]];
    cout << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/294300/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Online map

Class a 1111

subject

Enter our current location and destination, and the online map can recommend some routes.

Now your job is to recommend two routes to users: one is the shortest route and the other is the fastest route.

Ensure that there is at least one route between the two places for any inquiry.

Input format
The first row contains two integers N and m, indicating that there are N intersections (No. 0 ∼ N − 1) and M streets in the map.

Next, line M, each line describes a street, and the format is as follows:

V1 V2 one-way length time
V1 and V2 are the numbers of two intersections, indicating that there is a street between the two intersections. If one-way is 1, it means that the street is a one-way street and can only go to V2 from V1. If it is 0, it means it is a two-way street and can pass freely. Length is the length of the street and time is the time spent passing through the street.

The last line will give the numbers of the starting and ending intersections.

Output format
The first line outputs the route with the shortest distance and the shortest distance D, with the format as follows:

Distance = D: source -> v1 -> ... -> destination
The second line outputs the route with the fastest time and the shortest time T. The format is as follows:

Time = T: source -> w1 -> ... -> destination
If the shortest route is not unique, the route with the shortest time is output (ensure uniqueness).

If the fastest route is not unique, the route with the least intersection will be output (ensure uniqueness).

If the intersection sequence of the shortest route and the fastest route is exactly the same, output the two information in one line in the following format:

Distance = D; Time = T: source -> u1 -> ... -> destination
Data range
2≤N≤500,
1≤M≤N(N−1)2,
The length and time of each road shall not exceed 1000.
Duplicate streets may occur between any two intersections( This is different from the official website)

Input example 1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5
Output example 1:
Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5
Input example 2:
7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5
Output example 2:
Distance = 3; Time = 4: 3 -> 2 -> 5
Difficulty: medium
Time / space limit: 0.4s/64mb
Total number of passes: 408
Total attempts: 1026
Source: PAT class a real problem 1111

thought

Use Dijkstra twice
Find the shortest path for the first time and the fastest one
To record the path and time
Find the fastest path for the second time, and the one with the least number of intersections
Record the time and number of intersections

Own code

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int N = 510;
int dist[N], tt[N], d[N][N], ti[N][N], sum[N];
int n, m, S,T;
int dijkstra(int type, vector<int> &path){
    memset(dist, 0x3f, sizeof dist);
    memset(tt, 0x3f, sizeof tt);
    dist[S] = 0, tt[S] = 0;
    int i, j, pre[N];
    bool st[N];
    for(i = 0; i < n; i ++){
        int t = -1;
        for(j = 0; j < n; j ++){
            if(!st[j] && (t == -1 || dist[j] < dist[t])){
                t = j;
            }
        }
        st[t] = true;
        if(type == 1){
            for(j = 0; j < n; j ++){
                if(dist[j] > dist[t] + d[t][j]){
                    dist[j] = dist[t] + d[t][j];
                    tt[j] = tt[t] + ti[t][j];
                    pre[j] = t;
                }
                else if(dist[j] == dist[t] + d[t][j] && tt[j] > tt[t] + ti[t][j]){
                    tt[j] = tt[t] + ti[t][j];
                    pre[j] = t;
                }
            }
        }
        else if(type == 2){
            for(j = 0; j < n; j ++){
                if(dist[j] > dist[t] + ti[t][j]){
                    dist[j] = dist[t] + ti[t][j];
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
                else if(dist[j] == dist[t] + d[t][j] && sum[j] > sum[t] + 1){
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
            }
        }
    }
    path.push_back(S);
    vector<int> temp;
    for(i = T; i != S; i = pre[i]) temp.push_back(i);
    for(i = temp.size() - 1; i >= 0; i --) path.push_back(temp[i]);
    
    return dist[T];
}
int main(){
    int i;
    cin>>n>>m;
    memset(d, 0x3f, sizeof d);
    memset(ti, 0x3f, sizeof ti);
    for(i = 0; i < m; i ++){
        int a, b, is_oneway, length, tim;
        cin>>a>>b>>is_oneway>>length>>tim;
        if(is_oneway){
            d[a][b] = min(d[a][b], length);
            ti[a][b] = min(ti[a][b], tim);
        }
        else{
            d[a][b] = d[b][a] = min(d[a][b], length);
            ti[a][b] = ti[b][a] = min(ti[a][b], tim);            
        }
    }
    cin>>S>>T;
    vector<int> path1, path2;
    int res1 = dijkstra(1, path1);
    int res2 = dijkstra(2, path2);
    if(path1 == path2){
        cout<<"Distance = "<<res1<<"; Time = "<<res2<<": "<<path1[0];
        for(i = 1; i < path1.size(); i ++)
            cout<<" -> "<<path1[i];
        cout<<endl;
    }
    else{
        cout<<"Distance = "<<res1<<": "<<path1[0];
        for(i = 1; i < path1.size(); i ++)
            cout<<" -> "<<path1[i];
        cout<<endl;
        cout<<"Time = "<<res2<<": "<<path2[0];
        for(i = 1; i < path2.size(); i ++)
            cout<<" -> "<<path2[i];
        cout<<endl;
    }
    
}

y total code

#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 510, M = N * N;

int n, m, S, T;
int h[N], e[M], w1[M], w2[M], ne[M], idx;
int dist1[N], dist2[N], pre[N];
bool st[N];

void add(int a, int b, int c, int d)
{
    e[idx] = b, w1[idx] = c, w2[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;
}

pair<int, string> dijkstra(int w1[], int w2[], int type)
{
    memset(dist1, 0x3f, sizeof dist1);
    memset(dist2, 0x3f, sizeof dist2);
    memset(st, 0, sizeof st);
    dist1[S] = dist2[S] = 0;

    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 0; j < n; j ++ )
            if (!st[j] && (t == -1 || dist1[t] > dist1[j]))
                t = j;
        st[t] = true;
        for (int u = h[t]; ~u; u = ne[u])
        {
            int j = e[u];
            int cost;
            if (type == 0) cost = w2[u];
            else cost = 1;

            if (dist1[j] > dist1[t] + w1[u])
            {
                dist1[j] = dist1[t] + w1[u];
                dist2[j] = dist2[t] + cost;
                pre[j] = t;
            }
            else if (dist1[j] == dist1[t] + w1[u])
            {
                if (dist2[j] > dist2[t] + cost)
                {
                    dist2[j] = dist2[t] + cost;
                    pre[j] = t;
                }
            }
        }
    }

    vector<int> path;
    for (int i = T; i != S; i = pre[i]) path.push_back(i);

    pair<int, string> res;
    res.first = dist1[T];
    res.second = to_string(S);
    for (int i = path.size() - 1; i >= 0; i -- )
        res.second += " -> " + to_string(path[i]);
    return res;
}

int main()
{
    cin >> n >> m;

    memset(h, -1, sizeof h);
    while (m -- )
    {
        int a, b, t, c, d;
        cin >> a >> b >> t >> c >> d;
        add(a, b, c, d);
        if (!t) add(b, a, c, d);
    }

    cin >> S >> T;

    auto A = dijkstra(w1, w2, 0);
    auto B = dijkstra(w2, w1, 1);

    if (A.second != B.second)
    {
        printf("Distance = %d: %s\n", A.first, A.second.c_str());
        printf("Time = %d: %s\n", B.first, B.second.c_str());
    }
    else
    {
        printf("Distance = %d; Time = %d: %s\n", A.first, B.first, A.second.c_str());
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/294319/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Hamiltonian loop

subject

Own code

y total code

Euler loop

Class a 1126

subject

In graph theory, Eulerian path is a path in a graph, which satisfies that each edge is visited exactly once.

The Euler loop is an Euler path that starts and ends at the same vertex.

They were first proposed by Euler in 1736 when he solved the famous problem of the Seven Bridges in konisburg.

It is proved that if the degrees of all vertices of a connected graph are even, then the connected graph has an Euler loop, and the graph is called an Euler graph.

If the degrees of two vertices in a connected graph are odd and the degrees of other vertices are even, all Euler paths start from one vertex with odd degrees and end at the other vertex with odd degrees.

A graph with an Euler path but no Euler loop is called a semi Euler graph.

Now, given an undirected graph, please judge whether it is Euler, semi Euler or non Euler.

Input format
The first row contains two integers N and M, representing the number of points and edges of the undirected graph.

The next M lines contain two integers a and b, indicating that there is an edge between points a and b.

All points are numbered from 1 ∼ N.

Output format
First, the degrees of each point in point 1 ∼ N are output sequentially in the first row.

The second line outputs the judgment of the graph, including Euler, semi Euler and non Euler.

There must be no extra spaces at the end of the line.

Data range
1≤N≤500,
1≤M≤N(N−1)2
Input example 1:
7 12
5 7
1 2
1 3
2 3
2 4
3 4
5 2
7 6
6 3
4 5
6 4
5 6
Output example 1:
2 4 4 4 4 4 2
Eulerian
Input example 2:
6 10
1 2
1 3
2 3
2 4
3 4
5 2
6 3
4 5
6 4
5 6
Output example 2:
2 4 4 4 3 3
Semi-Eulerian
Input example 3:
5 8
1 2
2 5
5 4
4 1
1 3
3 2
3 4
5 3
Output example 3:
3 3 4 3 3
Non-Eulerian

thought

Euler graph-1, connected 2, the degree of all points is even
Semi Euler graph 1, connected 2 and degree 2 are odd numbers, and the rest are even numbers

Judge the connectivity and the number of connected blocks

//Judge the connectivity and the number of connectivity blocks
int dfs(int u)
{
    st[u] = true;

    int res = 1;
    for (int i = 1; i <= n; i ++ )
        if (!st[i] && g[u][i])
            res += dfs(i);

    return res;
}

Own code

/*Judge the connectivity and the number of connectivity blocks
int dfs(int u)
{
    st[u] = true;

    int res = 1;
    for (int i = 1; i <= n; i ++ )
        if (!st[i] && g[u][i])
            res += dfs(i);

    return res;
}
*/





//Euler graph-1, connected 2, the degree of all points is even
//Semi Eulerian graph 1, connected 2, 2 odd numbers, and the rest are even numbers

#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int g[N][N], cnt[N];
bool st[N];

int n, m;
void dfs(int u){
    st[u] = true;
    for(int i = 1; i <= n; i ++){
        if(g[u][i] && !st[i])
            dfs(i);
    }
}
bool DFS(int u){
    dfs(u);
    for(int i = 1; i <= n; i ++){
        if(!st[i]) return false;
    }
    return true;
}
int main(){
    cin>>n>>m;
    for(int i = 0; i < m; i ++){
        int a, b;
        cin>>a>>b;
        g[a][b] = 1;
        g[b][a] = 1;
        cnt[a] ++;
        cnt[b] ++;
    }
    bool flag = DFS(1), is_oula, is_midoula;
    int count = 0;
    for(int i = 1; i <= n; i ++){
        if(i > 1) cout<<" ";
        printf("%d", cnt[i]);
        if(cnt[i] % 2) count++;
    }
    cout<<endl;
    if(flag && count == 0){
        cout<<"Eulerian"<<endl;
    }
    else if(flag && count == 2){
        cout<<"Semi-Eulerian"<<endl;
    }
    else{
        cout<<"Non-Eulerian"<<endl;
    }
}

y total code

#include <cstring>
#include <iostream>

using namespace std;

const int N = 510;

int n, m;
bool g[N][N], st[N];
int d[N];

int dfs(int u)
{
    st[u] = true;

    int res = 1;
    for (int i = 1; i <= n; i ++ )
        if (!st[i] && g[u][i])
            res += dfs(i);

    return res;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ )
    {
        int a, b;
        cin >> a >> b;
        g[a][b] = g[b][a] = true;
        d[a] ++, d[b] ++ ;
    }

    int cnt = dfs(1);

    cout << d[1];
    for (int i = 2; i <= n; i ++ ) cout << ' ' << d[i];
    cout << endl;
    if (cnt == n)
    {
        int s = 0;
        for (int i = 1; i <= n; i ++ )
            if (d[i] % 2)
                s ++ ;

        if (s == 0) puts("Eulerian");
        else if (s == 2) puts("Semi-Eulerian");
        else puts("Non-Eulerian");
    }
    else puts("Non-Eulerian");

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295441/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Subway Map

subject

In big cities, the subway system always looks so complex to tourists.

In order to make you understand this, the following figure shows a map of Beijing subway.

Now, please help write a program to find the fastest way to reach its destination given the starting position of the user.

55799c23-4bdb-4e32-af7f-6d41accfdd2b.jpg

Input format
The first line contains a positive integer N, indicating the number of subway lines.

Next, line N and line i describe line i in the following format (subway lines are two-way):

M S[1] S[2] ... S[M]

Where M is the number of stations and S[i] is the number of stations along the line (the station number is a 4-digit number from 0000 to 9999).

Ensure that these stations are given according to the sequence of subway travel, that is, the subway will drive directly from S[i] to S[i+1].

Note that there may be a loop, but there is no self loop (that is, the subway starts from S and drives directly to S without passing through any station).

Each station interval belongs to only one unique line.

Some lines may cross each other at some stations (transfer stations), but when no station can be used as a transfer station, more than 5 lines intersect at the station.

After describing the subway line information, it contains a line of integer K, indicating the number of inquiries.

Next, line K, each line describes a query, including two station numbers, indicating the origin and destination respectively.

The following is an example diagram:

932c8f1b-7dd5-489d-a774-a91c1fabba7f.jpg

Ensure that all stations can be reached and ask if the station number is legal.

Output format
For each query, first output the minimum number of stops, and then output the best route in the following format:

Take Line#X1 from S1 to S2.
Take Line#X2 from S2 to S3.
...
Where Xi is the line number and Si is the station number. Except for the departure station and terminal station, only the transfer station is output.

If the fastest line is not unique, the line with the least transfer times will be output to ensure uniqueness.

Data range
1≤N≤100,
1≤M≤100,
1≤K≤10
Input example:
4
7 1001 3212 1003 1204 1005 1306 7797
9 9988 2333 1204 2006 2005 2004 2003 2302 2001
13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011
4 6666 8432 4011 1306
3
3011 3013
6666 2001
2004 3001
Output example:
2
Take Line#3 from 3011 to 3013.
10
Take Line#4 from 6666 to 1306.
Take Line#3 from 1306 to 2302.
Take Line#2 from 2302 to 2001.
6
Take Line#2 from 2004 to 1204.
Take Line#1 from 1204 to 1306.
Take Line#3 from 1306 to 3001.

thought

This problem is very classic. You should fully understand it

The key to this problem is to connect each point in a subway line and save it as a corresponding edge and corresponding point. In this way, an edge can represent this line
On the basis of the above, the least number of times becomes the least number of sides
So the problem becomes the shortest path problem with the least number of sides

This problem requires heap optimization, because there are many points, it is impossible to traverse to find the minimum value
So heap optimization is used to solve
When storing the number of edges, you can save the distance and the route together

Dijkstra for heap optimization

while(heap.size()){//Because the points are scattered, we use the heap optimization method
        
        auto t = heap.top().second;
        heap.pop();
        
        //st[t] = true;
        if(t == b) break;//This is very important. The heap does not necessarily become empty, so if the end point is determined, exit the loop
        if(st[t]) continue;//For heap optimization, there is no judgment on st, so if ST has been determined, continue directly
        
        st[t] = true;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            if(d[j] > d[t] + w[i]){
                d[j] = d[t] + w[i];
                heap.push({d[j], j});
                cnt[j] = cnt[t] + 1;
                pre[j] = t;
                //info[j] = "Take Line#" + to_string(line[j]) + "from "+ to_string(t) +" to "+ to_string(j) <<endl;
            
                info[j] = "Take Line#" + to_ String (line[i]) + "from" + / / note that it is line[i], not line[j]
                get_number(t) + " to " + get_number(j) + ".";
            }
            else if(d[j] == d[t] + w[i]){
                if(cnt[j] > cnt[t] + 1){//If it is the case with fewer edges
                    cnt[j] = cnt[t] + 1;
                    pre[j] = t;
                    //info[j] = "Take Line#" + to_string(line[j]) + "from "+ to_string(t) +" to "+ to_string(j) <<endl;
                
                    info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                    get_number(t) + " to " + get_number(j) + ".";
                }
            }
        }
    }

Own code

//The key to this problem is to connect each point in a subway line and save it as a corresponding edge and corresponding point. In this way, an edge can represent this line
//On the basis of the above, the least number of times becomes the least number of sides
//So the problem becomes the shortest path problem with the least number of sides

//This problem requires heap optimization, because there are many points, it is impossible to traverse to find the minimum value
//So heap optimization is used to solve
//When storing the number of edges, you can save the distance and the route together


#include<iostream>
#include <cstring>
//#It seems that there is also a vector in the include < vector > queue, so there is no need to call it repeatedly
#include <queue>
#define x first
#define y second
using namespace std;
//const int N = 10001, M = 100000001;;

typedef pair<int, int> PII;
const int N = 10010, M = 1000010;

int n;
int h[N], e[M], w[M], line[M], ne[M], idx;
int d[N], cnt[N], pre[N];
int stops[N];
string info[N];
bool st[N];

string get_number(int x)
{
    char res[5];
    sprintf(res, "%04d", x);
    return res;
}

void add(int a, int b, int c, int id)
{
    e[idx] = b, w[idx] = c, line[idx] = id, ne[idx] = h[a], h[a] = idx ++ ;
}
/*
void dijkstra(int start, int end)
{
    memset(dist, 0x3f, sizeof dist);
    memset(cnt, 0x3f, sizeof cnt);
    memset(st, 0, sizeof st);

    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, start});
    dist[start] = cnt[start] = 0;

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.y;
        if (ver == end) break;
        if (st[ver]) continue;
        st[ver] = true;

        for (int i = h[ver]; ~i; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                cnt[j] = cnt[ver] + 1;
                pre[j] = ver;
                info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                    get_number(ver) + " to " + get_number(j) + ".";
                heap.push({dist[j], j});
            }
            else if (dist[j] == dist[ver] + w[i])
            {
                if (cnt[j] > cnt[ver] + 1)
                {
                    cnt[j] = cnt[ver] + 1;
                    pre[j] = ver;
                    info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                        get_number(ver) + " to " + get_number(j) + ".";
                }
            }
        }
    }

    cout << dist[end] << endl;
    vector<string> path;
    for (int i = end; i != start; i = pre[i])
        path.push_back(info[i]);

    for (int i = path.size() - 1; ~i; i -- )
        cout << path[i] << endl;
}
*/
void dijkstra(int a, int b){

    
    memset(d, 0x3f, sizeof d);//Yes set to 0x3f
    memset(cnt, 0x3f, sizeof cnt);
    memset(st, 0, sizeof st);

    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, a});
    d[a] = cnt[a] = 0;
    
    while(heap.size()){//Because the points are scattered, we use the heap optimization method
        
        auto t = heap.top().second;
        heap.pop();
        
        //st[t] = true;
        if(t == b) break;//This is very important. The heap does not necessarily become empty, so if the end point is determined, exit the loop
        if(st[t]) continue;//For heap optimization, there is no judgment on st, so if ST has been determined, continue directly
        
        st[t] = true;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            if(d[j] > d[t] + w[i]){
                d[j] = d[t] + w[i];
                heap.push({d[j], j});
                cnt[j] = cnt[t] + 1;
                pre[j] = t;
                //info[j] = "Take Line#" + to_string(line[j]) + "from "+ to_string(t) +" to "+ to_string(j) <<endl;
            
                info[j] = "Take Line#" + to_ String (line[i]) + "from" + / / note that it is line[i], not line[j]
                get_number(t) + " to " + get_number(j) + ".";
            }
            else if(d[j] == d[t] + w[i]){
                if(cnt[j] > cnt[t] + 1){//If it is the case with fewer edges
                    cnt[j] = cnt[t] + 1;
                    pre[j] = t;
                    //info[j] = "Take Line#" + to_string(line[j]) + "from "+ to_string(t) +" to "+ to_string(j) <<endl;
                
                    info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                    get_number(t) + " to " + get_number(j) + ".";
                }
            }
        }
    }
    cout<<d[b]<<endl;//Output distance
    vector<int> path;
    for(int i = b; i != a; i = pre[i]){
        path.push_back(i);
    }
    for(int i = path.size() - 1; i >= 0; i --){
        cout<<info[path[i]]<<endl;
    }
    
}
int main(){
    cin>>n;
    memset(h, -1, sizeof h);
    for(int i = 1; i <= n; i ++){
        int m;
        cin>>m;
        for(int j = 0; j < m; j ++){
            cin>>stops[j];
        }
        for(int j = 0; j < m; j ++){
            for(int k = 0; k < j; k ++){//Note that there is a very important point here, that is, it is possible that this line is a ring, and we want to take the shorter one
                int len;
                if(stops[0] != stops[m - 1]) len = j - k;
                else len = min(j - k, m - 1  + k - j);
                add(stops[j], stops[k], len, i);
                add(stops[k], stops[j], len, i);
            }
        }
    }
    int k;
    cin>>k;
    for(int i = 0; i < k; i ++){
        int a, b;
        cin>>a>>b;
        dijkstra(a, b);
    }
}

y total code

#include <iostream>
#include <cstring>
#include <queue>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 10010, M = 1000010;

int n;
int h[N], e[M], w[M], line[M], ne[M], idx;
int dist[N], cnt[N], pre[N];
int stops[N];
string info[N];
bool st[N];

string get_number(int x)
{
    char res[5];
    sprintf(res, "%04d", x);
    return res;
}

void add(int a, int b, int c, int id)
{
    e[idx] = b, w[idx] = c, line[idx] = id, ne[idx] = h[a], h[a] = idx ++ ;
}

void dijkstra(int start, int end)
{
    memset(dist, 0x3f, sizeof dist);
    memset(cnt, 0x3f, sizeof cnt);
    memset(st, 0, sizeof st);

    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, start});
    dist[start] = cnt[start] = 0;

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.y;
        if (ver == end) break;
        if (st[ver]) continue;
        st[ver] = true;

        for (int i = h[ver]; ~i; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                cnt[j] = cnt[ver] + 1;
                pre[j] = ver;
                info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                    get_number(ver) + " to " + get_number(j) + ".";
                heap.push({dist[j], j});
            }
            else if (dist[j] == dist[ver] + w[i])
            {
                if (cnt[j] > cnt[ver] + 1)
                {
                    cnt[j] = cnt[ver] + 1;
                    pre[j] = ver;
                    info[j] = "Take Line#" + to_string(line[i]) + " from " + 
                        get_number(ver) + " to " + get_number(j) + ".";
                }
            }
        }
    }

    cout << dist[end] << endl;
    vector<string> path;
    for (int i = end; i != start; i = pre[i])
        path.push_back(info[i]);

    for (int i = path.size() - 1; ~i; i -- )
        cout << path[i] << endl;
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i ++ )
    {
        int m;
        cin >> m;
        for (int j = 0; j < m; j ++ ) cin >> stops[j];

        for (int j = 0; j < m; j ++ )
            for (int k = 0; k < j; k ++ )
            {
                int len;
                if (stops[0] != stops[m - 1]) len = j - k;
                else len = min(j - k, m - 1 - j + k);

                add(stops[j], stops[k], len, i);
                add(stops[k], stops[j], len, i);
            }
    }

    int k;
    cin >> k;
    while (k -- )
    {
        int start, end;
        cin >> start >> end;
        dijkstra(start, end);
    }

    return 0;
}


Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295487/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Vertex overlay

Class a 1134

subject

If a vertex set in a graph can satisfy that every edge in the graph has at least one endpoint in the set, then the vertex set is the vertex cover of the graph.

Now, given a graph and several vertex sets, please judge whether these vertex sets are vertex covers of the graph.

Input format
The first row contains two integers N and M, representing the number of points and edges in the graph.

The next M lines contain two integers a and b, indicating that there is an edge between point a and point b.

Point number 0 ∼ N − 1.

It then contains an integer K representing the number of vertex sets queried.

Next, K lines, each line describes a set of query vertices, with the format as follows:

Nv V[1] V[2] ... V[Nv]
Nv is the number of points in the set, and V[i] is the number of points.

Output format
Each group of queries outputs a row of results. If it is vertex coverage, it outputs Yes, otherwise it outputs No.

Data range
1≤N,M≤104,
1≤K≤100,
1≤Nv≤N
Input example:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 0
2 4
5
4 0 3 8 4
6 6 1 7 5 4 9
3 1 8 4
2 2 8
7 9 8 7 6 5 4 2
Output example:
No
Yes
Yes
No
No

thought

Storing edges with struct
If you need to traverse all edges

Own code

#include<iostream>
#include <cstring>

using namespace std;
const int N = 1e4 + 10;
struct Node{
    int a, b;
}e[N];
bool st[N];
int main(){
    int n, m, k, t;
    cin>>n>>m;
    for(int i = 0; i < m; i ++){
        int a, b;
        cin>>a>>b;
        e[i].a = a, e[i].b = b;
    }
    cin>>k;
    for(int i = 0; i < k; i ++){
        cin>>t;
        int cnt = 0;

        memset(st, 0, sizeof st);
        
        for(int j = 0; j < t; j ++){
            int a;
            cin>>a;
            st[a] = true;
        }
        for(int j = 0; j < m; j ++){
            if(st[e[j].a] || st[e[j].b])
                cnt ++;
        }

        if(cnt == m) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

y total code

#include <iostream>
#include <cstring>

using namespace std;

const int N = 10010;

int n, m;
struct Edge
{
    int a, b;
}e[N];
bool st[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;

    int k;
    cin >> k;
    while (k -- )
    {
        int cnt;
        cin >> cnt;

        memset(st, 0, sizeof st);
        while (cnt -- )
        {
            int x;
            cin >> x;
            st[x] = true;
        }

        int i;
        for (i = 0; i < m; i ++ )
            if (!st[e[i].a] && !st[e[i].b])
                break;

        if (i == m) puts("Yes");
        else puts("No");
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295498/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

First contact

subject

thought

Own code

y total code

Largest group

Class a 1142

subject

In an undirected graph, if a vertex subset satisfies that any two different vertices in the subset are connected, then the vertex subset is called a clique.

If a clique cannot be expanded into a larger clique by adding a new vertex, the clique is called the largest clique.

Now, you need to judge whether a given vertex subset can form a maximum group.

Input format
The first row contains two integers Nv and Ne, representing the number of points and edges of the undirected graph, respectively.

Next, the Ne line contains two integers a and b, indicating that there is an edge between point a and point b.

All points are numbered from 1 to Nv.

The next line contains the integer M, indicating the number of queries.

Next, line M, each line describes a query vertex subset. First, it contains an integer k, indicating the number of points contained in the subset, and then contains k integers, indicating the number of K different vertices.

All numbers in a line are separated by a space.

Output format
Each group of queries outputs a conclusion in one line.

If the given subset is the largest clique, Yes is output. If it is a clique but not the largest clique, not maximum is output. If it is Not a Clique at all, Not a Clique is output.

Data range
1≤Nv≤200,
1≤Ne≤Nv(Nv−1)2,
1≤M≤100,
1≤K≤Nv
Input example:
8 10
5 6
7 8
6 4
3 6
4 5
2 3
8 2
2 7
5 3
3 4
6
4 5 4 3 6
3 2 8 7
2 2 3
1 1
3 4 3 6
3 3 2 1
Output example:
Yes
Yes
Yes
Yes
Not Maximal
Not a Clique

thought

It's the meaning of the topic. Just write it

Own code

#include <iostream>
using namespace std;
const int N = 210;
int g[N][N], q[N];
int main(){
    int n, m, k, t;
    cin>>n>>m;
    for(int i = 0; i < m; i ++){
        int a, b;
        cin>>a>>b;
        g[a][b] = 1;
        g[b][a] = 1;
    }
    cin>>k;
    for(int i = 0; i < k; i ++){
        cin>>t;
        for(int j = 0; j < t; j ++) cin>>q[j];
        
        bool flag = true;
        for(int j = 0; j < t; j ++){
            for(int p = 0; p < t; p ++){
                //cout<<q[j]<<" "<<q[p]<<" "<<g[q[j]][q[p]]<<endl;
                if(p != j && !g[q[j]][q[p]]){
                    flag = false;
                    break;
                }
            }
            if(!flag) break;
        }
        int cnt = 0;
        if(flag){
            for(int j = 1; j <= n; j ++){
                for(int p = 0; p < t; p ++){
                    if(q[p] != j && !g[j][q[p]]){
                        cnt++;
                        break;
                    }
                }
            }
            if(cnt == n - t) cout<<"Yes"<<endl;
            else cout<<"Not Maximal"<<endl;
        }
        else{
            cout<<"Not a Clique"<<endl;
        }
    }
}

y total code

#include <iostream>
#include <cstring>

using namespace std;

const int N = 210;

int n, m;
bool g[N][N], st[N];
int vers[N];

bool check_clique(int cnt)
{
    for (int i = 0; i < cnt; i ++ )
        for (int j = 0; j < i; j ++ )
            if (!g[vers[i]][vers[j]])
                return false;
    return true;
}

bool check_maximum(int cnt)
{
    memset(st, 0, sizeof st);
    for (int i = 0; i < cnt; i ++ )
        st[vers[i]] = true;

    for (int i = 1; i <= n; i ++ )
        if (!st[i])
        {
            bool success = true;
            for (int j = 0; j < cnt; j ++ )
                if (!g[i][vers[j]])
                {
                    success = false;
                    break;
                }

            if (success) return false;
        }

    return true;
}

int main()
{
    cin >> n >> m;
    while (m -- )
    {
        int a, b;
        cin >> a >> b;
        g[a][b] = g[b][a] = true;
    }

    int k;
    cin >> k;
    while (k -- )
    {
        int cnt;
        cin >> cnt;
        for (int i = 0; i < cnt; i ++ ) cin >> vers[i];
        if (check_clique(cnt))
        {
            if (check_maximum(cnt)) puts("Yes");
            else puts("Not Maximal");
        }
        else puts("Not a Clique");
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295529/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Topological sorting

subject

This is a question given in the 2018 postgraduate entrance examination:

Which of the following options is not a topological sequence obtained from a given directed graph?

Now, please write a program to test each option.

5d35ed2a-4d19-4f13-bf3f-35ed59cebf05.jpg

Input format
The first row contains two integers N and M, representing the number of points and edges of the directed graph, respectively.

Next M lines, each giving the start and end of an edge.

Points are numbered from 1 to N.

The next line contains an integer K, indicating the number of queries.

Next, K rows, each containing an arrangement of all points.

The numbers in a line are separated by spaces.

Output format
Output the numbers of all query sequences that are not topological sequences in one line.

The query sequence number starts from 0.

There shall be no extra spaces at the beginning and end of the line to ensure that there is at least one solution.

Data range
1≤N≤1000,
1≤M≤10000,
1≤K≤100
Input example:
6 8
1 2
1 3
5 2
5 4
2 3
2 6
3 4
6 4
5
1 5 2 3 6 4
5 1 2 6 3 4
5 1 2 3 6 4
5 2 1 6 3 4
1 2 3 4 5 6
Output example:
3 4

thought

Idea of y total code to be updated

Own code

I mainly simulate the whole topological sorting process to judge

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e4 + 10;
int g[N][N], a[N], n;
bool check(vector<int> d){
    
    for(int i = 0; i < n; i ++){
        if(d[a[i]] == 0){
            for(int j = 1; j <= n; j ++){
                if(g[a[i]][j]){
                    d[j]--;
                }
            }
        }
        else return false;
    }
    return true;
}
int main(){
    int m;
    cin>>n>>m;
    vector<int> d(N);
    for(int i = 0; i < m; i ++){
        int a, b;
        scanf("%d %d", &a, &b);
        g[a][b] = 1;
        d[b] ++;
    }
    int k;
    cin>>k;
    bool is_first = true;
    for(int i = 0; i < k; i ++){
        vector<int> temp = d;
        for(int j = 0; j < n; j ++)
            scanf("%d", &a[j]);
        
        if(!check(temp)){
            if(is_first) is_first = false;
            else printf(" ");
            printf("%d", i);
        }
        
    }
}

y total code

#include <iostream>
#include <cstring>

using namespace std;

const int N = 1010, M = 10010;

int n, m;
struct Edge
{
    int a, b;
}e[M];
int p[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;

    int k;
    cin >> k;

    bool is_first = true;
    for (int i = 0; i < k; i ++ )
    {
        for (int j = 1; j <= n; j ++ )
        {
            int x;
            cin >> x;
            p[x] = j;
        }

        bool success = true;
        for (int j = 0; j < m; j ++ )
            if (p[e[j].a] > p[e[j].b])
            {
                success = false;
                break;
            }

        if (!success)
        {
            if (is_first) is_first = false;
            else cout << ' ';
            cout << i;
        }
    }

    cout << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295539/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

traveling salesman problem

subject

"Traveling salesman problem" is such a question: "give a list of cities and the distance between each pair of cities, and what is the shortest route to visit each city and return to the original city?"

This is a NP hard problem in combinatorial optimization, which is very important in operational research and theoretical computer science.

In this problem, please find the path closest to the solution of the traveling salesman problem from the given path list.

Input format
The first row contains two integers N and M, representing the number of cities and the number of edges in the undirected graph, respectively.

Next M lines, each line describes an edge in the format of city1city2 Dist, where the city number is from 1 to N, and Dist is positive and no more than 100.

The next line contains an integer K representing the number of given paths.

Next, line K describes the path in the following format:

n C1 C2 ... Cn
n represents the number of cities passed by a given path, and Ci is the number of cities passed by the path.

Output format
For each path, output Path X: TotalDist (Description) on one line.

Where X is the path number (starting from 1), TotalDist represents the total distance of the path (if the distance does not exist, NA is output), and Description is one of the following:

TS simple cycle, if this is a simple loop to access each city.
TS cycle, if this is a loop that accesses each city, but not a simple loop.
Not a TS cycle, if this is not a loop that accesses each city.
In the last line, output Shortest Dist(X) = TotalDist, where X is the loop number closest to the solution of the traveling salesman problem, and TotalDist is its total distance.

There is guaranteed to be a unique solution.

Data range
2<N≤200,
N−1≤M≤N(N−1)2,
1≤K≤1000,
1≤n≤300
Input example:
6 10
6 2 1
3 4 1
1 5 1
2 5 1
3 1 8
4 1 6
1 6 1
6 3 1
1 2 1
4 5 1
7
7 5 1 4 3 6 2 5
7 6 1 3 4 5 2 6
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 2 5 4 3 1
7 6 3 2 5 4 1 6
Output example:
Path 1: 11 (TS simple cycle)
Path 2: 13 (TS simple cycle)
Path 3: 10 (Not a TS cycle)
Path 4: 8 (TS cycle)
Path 5: 3 (Not a TS cycle)
Path 6: 13 (Not a TS cycle)
Path 7: NA (Not a TS cycle)
Shortest Dist(4) = 8

thought

A simple loop passes through each point only once
Instead of a simple loop, it may go through multiple times

Own code

#include <iostream>
#include <unordered_map>
#include <cstring>
using namespace std;
const int N = 1e3 + 10;
int g[N][N], a[N];
int main(){
    int n, m;
    cin>>n>>m;
    memset(g, 0x3f, sizeof g);
    for(int i = 0; i < m; i ++){
        int a, b, distance;
        cin>>a>>b>>distance;
        g[a][b] = distance;
        g[b][a] = distance;
    }
    int k;
    cin>>k;
    int min_res = 0x3f3f3f3f, min_index = 0;
    for(int i = 0; i < k; i ++){
        int t;
        cin>>t;
        int num = 0, sum = 0;
        bool flag2 = false;
        unordered_map<int, int> hash;

        for(int j = 0;j < t; j ++){
            cin>>a[j];
            if(!hash.count(a[j])){
                hash[a[j]] = 1;
                num++;
            }
            else{
                hash[a[j]] ++;
                if(j != t - 1) flag2 = true;
            }
            if(j && g[a[j]][a[j - 1]] == 0x3f3f3f3f){
                sum = 0x3f3f3f3f;
            }
            else{
                if(j) sum += g[a[j]][a[j - 1]];
            }
        }
        

        if(num == n && a[0] == a[t - 1] && sum < 0x3f3f3f3f){
            printf("Path %d: %d", i + 1, sum);
            if(!flag2) printf(" (TS simple cycle)\n");
            else printf(" (TS cycle)\n");
            
            if(sum < min_res) min_res = sum, min_index = i + 1;
        }
        else{
            if(sum >= 0x3f3f3f3f) printf("Path %d: NA", i + 1);
            else printf("Path %d: %d", i + 1, sum);
            printf(" (Not a TS cycle)\n");
        }
    }
    printf("Shortest Dist(%d) = %d", min_index, min_res);
}

y total code

#include <iostream>
#include <cstring>

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;

int n, m;
int d[N][N], vers[310];
bool st[N];

int main()
{
    cin >> n >> m;
    memset(d, 0x3f, sizeof d);
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = d[b][a] = c;
    }

    int k;
    cin >> k;

    int min_dist = INF, min_id;
    for (int T = 1; T <= k; T ++ )
    {
        int cnt;
        cin >> cnt;
        for (int i = 0; i < cnt; i ++ ) cin >> vers[i];

        int sum = 0;
        bool success = true;
        memset(st, 0, sizeof st);
        for (int i = 0; i + 1 < cnt; i ++ )
        {
            int a = vers[i], b = vers[i + 1];
            if (d[a][b] == INF)
            {
                sum = -1;
                success = false;
                break;
            }
            else sum += d[a][b];
            st[a] = true;
        }

        for (int i = 1; i <= n; i ++ )
            if (!st[i])
            {
                success = false;
                break;
            }

        if (vers[0] != vers[cnt - 1]) success = false;

        if (sum == -1) printf("Path %d: NA (Not a TS cycle)\n", T);
        else
        {
            if (!success) printf("Path %d: %d (Not a TS cycle)\n", T, sum);
            else
            {
                if (cnt == n + 1) printf("Path %d: %d (TS simple cycle)\n", T, sum);
                else printf("Path %d: %d (TS cycle)\n", T, sum);

                if (min_dist > sum)
                {
                    min_dist = sum;
                    min_id = T;
                }
            }
        }
    }

    printf("Shortest Dist(%d) = %d\n", min_id, min_dist);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295563/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Vertex Shader

subject

A suitable vertex coloring is to mark each vertex in the graph with various colors so that the colors of the two endpoints of each edge are different.

If a suitable vertex shading scheme uses a total of K different colors, it is called appropriate k-coloring.

Now, you need to determine whether a given coloring scheme is a suitable k coloring scheme.

Input format
The first row contains two integers N and M, representing the number of points and edges, respectively.

The next M lines contain two integers a and b, indicating that there is an edge between point a and point b.

All points are numbered from 0 to N − 1.

The next line contains an integer K, indicating the coloring scheme you need to judge.

Next, K rows, each containing N colors, where the ith color represents the color of the ith point.

The color is expressed as a non negative integer and does not exceed the int range.

Output format
For each shading scheme, if it is an appropriate K shading scheme, a row of k-coloring is output.

If it is not an appropriate shading scheme, a line No is output.

Data range
1≤N,M≤104,
1≤K≤100
Input example:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 0
2 4
4
0 1 0 1 4 1 0 1 3 0
0 1 0 1 4 1 0 1 0 0
8 1 0 1 4 1 0 5 3 0
1 2 3 4 5 6 7 8 8 9
Output example:
4-coloring
No
6-coloring
No
Difficulty: simple
Time / space limit: 0.9s/64mb
Total number of passes: 354
Total attempts: 716
Source: PAT class a real question 1154
Algorithm label

thought

This problem does not need to be complicated to dichotomize the colored graph. It is OK to directly judge the inequality of each edge

Own code

//To complicate the problem, you don't need to use dfs, you just need to judge whether each edge is different

#include <iostream>
#include <cstring>
#include <unordered_set>

using namespace std;

const int N = 10010;

int n, m;
struct Edge
{
    int a, b;
}e[N];
int color[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;

    int k;
    cin >> k;
    while (k -- )
    {
        for (int i = 0; i < n; i ++ ) cin >> color[i];

        bool success = true;
        for (int i = 0; i < m; i ++ )
            if (color[e[i].a] == color[e[i].b])
            {
                success = false;
                break;
            }

        if (success)
        {
            unordered_set<int> S;
            for (int i = 0; i < n; i ++ ) S.insert(color[i]);
            printf("%d-coloring\n", S.size());
        }
        else puts("No");
    }

    return 0;
}




/*#include <iostream>
#include <unordered_set>
#include <cstring>
using namespace std;
const int N = 1e4 + 10;
int st[N], h[N], e[N * N], ne[N * N],c[N], idx = 0;
int cnt = 0;
unordered_set<int> hash_set;
bool dfs(int u){
    st[u] = true;
    if(!hash_set.count(c[u])){
        cnt++;
        hash_set.insert(c[u]);
    }
    for(int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];
        if(!st[j]){
           if(c[j] == c[u]) {
                return false;
            }
            if(!dfs(j)) return false;
        }
    }
    return true;
}
void add(int a, int b){
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}
int main(){
    int n, m;
    cin>>n>>m;
    memset(h, -1, sizeof h);
    for(int i = 0; i < m; i ++){
        int a, b;
        cin>>a>>b;
        add(a, b);
        add(b, a);
    }
    int k;
    cin>>k;
    for(int i = 0; i < k; i ++){
        memset(c, 0, sizeof c);
        memset(st, 0, sizeof st);
        for(int j = 0; j < n; j ++)
            cin>>c[j];
        cnt = 0;
        hash_set.clear();
        bool flag = true;
        for(int j = 0; j < n; j ++){
            if(!st[j]){
                flag = dfs(j);
                if(!flag) break;
            }
        }
        if(!flag)cout<<"No"<<endl;
        else{
            cout<<cnt<<"-coloring"<<endl;
        }
    }
    
}*/

y total code

#include <iostream>
#include <cstring>
#include <unordered_set>

using namespace std;

const int N = 10010;

int n, m;
struct Edge
{
    int a, b;
}e[N];
int color[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;

    int k;
    cin >> k;
    while (k -- )
    {
        for (int i = 0; i < n; i ++ ) cin >> color[i];

        bool success = true;
        for (int i = 0; i < m; i ++ )
            if (color[e[i].a] == color[e[i].b])
            {
                success = false;
                break;
            }

        if (success)
        {
            unordered_set<int> S;
            for (int i = 0; i < n; i ++ ) S.insert(color[i]);
            printf("%d-coloring\n", S.size());
        }
        else puts("No");
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/295574/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Extended bipartite graph

int n;      // n represents the number of points
int h[N], e[M], ne[M], idx;     // Adjacency table storage graph
int color[N];       // Represents the color of each point, - 1 represents undyed, 0 represents white, and 1 represents black

// Parameters: u represents the current node and c represents the color of the current point
bool dfs(int u, int c)
{
    color[u] = c;
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (color[j] == -1)
        {
            if (!dfs(j, !c)) return false;
        }
        else if (color[j] == c) return false;
    }

    return true;
}

bool check()
{
    memset(color, -1, sizeof color);
    bool flag = true;
    for (int i = 1; i <= n; i ++ )
        if (color[i] == -1)
            if (!dfs(i, 0))
            {
                flag = false;
                break;
            }
    return flag;
}

Author: yxc
 Link: https://www.acwing.com/blog/content/405/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Public bicycle management

subject

thought

Own code

y total code

gas station

subject

The gas station must be located as far as possible from the nearest house.

At the same time, it must ensure that all houses are within the scope of its services.

Now, the city map and several candidate locations of gas stations are given. Please provide the best suggestions.

If there are multiple solutions, output the solution with the smallest average distance between the selected location and all houses.

If such a solution is still not unique, please output the solution with the smallest location number.

Input format
The first row contains four integers N, the total number of houses, M, the total number of candidate locations for gas stations, K, the total number of roads connecting houses or gas stations, and Ds, the maximum service range of gas stations.

All houses are numbered from 1 to N, and all gas station candidate locations are numbered from G1 to GM.

Next, there are K lines. The format of each line is as follows:

P1 P2 Dist
Where P1 and P2 represent the numbers of two houses or gas stations connected by an undirected Road, and Dist is the road length, which is an integer.

Output format
The first line outputs the number of the selected position.

The second line outputs the distance between the gas station and the nearest house and the average distance between all houses, accurate to one decimal place.

If the solution does not exist, No Solution is output.

Data range
1≤N≤103,
1≤M≤10,
1≤K≤104,
1≤Ds≤200,
1≤Dist≤5000
Input example 1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
Output example 1:
G1
2.0 3.3
Input example 2:
2 1 2 10
1 G1 9
2 G1 20
Output example 2:
No Solution

thought

Own code

//Problems encountered in debugging
//Note that user G may be equal to 10, so when converting, you should not only consider the sample data, but also consider the given value range

#include<iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct station{
    string id;
    double nearest;
    double ave;
    bool operator < (const station &s) const{
        if(nearest != s.nearest) return nearest > s.nearest;
        if(ave != s.ave) return ave < s.ave;
        return id < s.id; 
    }
};
const int N = 1e3+ 30;
int g[N][N], dist[N];
bool st[N];
vector<station> record;
int n, m, k, ds;
int convert(string a){
    if(a[0] == 'G'){
        if(a.size() == 2)
            return a[1] - '0' + n;
        else
            return n + 10;
    }
    else{
        int sum = 0;
        for(int i = 0; i < a.size(); i ++)
            sum = sum * 10 + a[i] - '0';
        return sum;
    }
}
string decode(int num){
    if(num > n) return "G" + to_string(num - n);
    else return to_string(num);
}
void djkstra(int start){
    
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);

    dist[start] = 0;
    for (int i = 0; i < n + m; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n + m; j ++ )
            if (!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;

        st[t] = true;

        for (int j = 1; j <= n + m; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }


    int sum = 0;
    bool flag = true;
    int res = 0x3f3f3f3f;
    for(int i = 1; i <= n; i ++){
        if(dist[i] > ds) {
            flag = false;
            break;
        }
        sum += dist[i];
        if(dist[i] < res) res = dist[i];
    }
    if(flag){
        double ave = (double) sum / n + 1e-8;
        double nearest = res;
        record.push_back({decode(start), nearest, ave});
    }
}

int main(){
    int i, j;
    cin>>n>>m>>k>>ds;
    memset(g, 0x3f, sizeof g);
    for(i = 0; i < k; i ++){
        int distance;
        string a, b;
        cin>>a>>b>>distance;
        g[convert(a)][convert(b)] = distance;
        g[convert(b)][convert(a)] = distance;
    }
    for(i = 1; i <= m; i ++){
        string a = "G" + to_string(i);
        djkstra(convert(a));
    }
    sort(record.begin(), record.end());
    if(record.size()){
        cout<<record[0].id<<endl;
        printf("%.1lf %.1lf\n", record[0].nearest, record[0].ave);}//It is found that the system retains one decimal place for 3.25, which is 3.2, so we need to add a 1e-8 for this case
    else
        cout<<"No Solution"<<endl;
}

y total code

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1020, INF = 0x3f3f3f3f;

int n, m, k, D;
int g[N][N];
int dist[N];
bool st[N];

int get(string s)
{
    if (s[0] == 'G') return n + stoi(s.substr(1));
    return stoi(s);
}

void dijkstra(int start, int &mind, int &sumd)
{
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);

    dist[start] = 0;
    for (int i = 0; i < n + m; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n + m; j ++ )
            if (!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;

        st[t] = true;

        for (int j = 1; j <= n + m; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }

    for (int i = 1; i <= n; i ++ )
        if (dist[i] > D)
        {
            mind = -INF;
            return;
        }

    mind = INF, sumd = 0;
    for (int i = 1; i <= n; i ++ )
    {
        mind = min(mind, dist[i]);
        sumd += dist[i];
    }
}

int main()
{
    cin >> n >> m >> k >> D;

    memset(g, 0x3f, sizeof g);
    while (k -- )
    {
        string a, b;
        int z;
        cin >> a >> b >> z;
        int x = get(a), y = get(b);

        g[x][y] = g[y][x] = min(g[x][y], z);
    }

    int res = -1, mind = 0, sumd = INF;
    for (int i = n + 1; i <= n + m; i ++ )
    {
        int d1, d2;
        dijkstra(i, d1, d2);

        if (d1 > mind) res = i, mind = d1, sumd = d2;
        else if (d1 == mind && d2 < sumd) res = i, sumd = d2;
    }

    if (res == -1) puts("No Solution");
    else printf("G%d\n%.1lf %.1lf\n", res - n, (double)mind, (double)sumd / n + 1e-8);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/323579/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Microblog forwarding

subject

Microblog is called Chinese version of Twitter.

Users on microblog may not only have many followers, but also pay attention to many other users.

Therefore, a social network based on these concerns is formed.

When a user posts a post on the microblog, all his / her followers can view and forward his / her post, and then their followers can forward the content again

Now, given a social network, assuming that only L-layer followers are considered, please calculate the maximum possible forwarding amount of posts of some users.

supplement
If B is the follower of A and C is the follower of B, then the first layer follower of A is B and the second layer follower is C.

Input format
The first line contains two integers. N represents the number of users and L represents the number of layers of followers to be considered.

It is assumed that the number of all users is 1 ∼ N.

Next, there are N lines. Each line contains the attention information of a user. The format is as follows:

M[i] user_list[i]
M[i] is the total number of people concerned by the ith user, user_list[i] is the number list of M[i] users concerned by the ith user.

The last line first contains an integer K, indicating the number of queries, and then contains K user numbers, indicating the maximum possible forwarding amount of posts asking these people.

Output format
In order, each line outputs the maximum possible forwarding amount of a respondent's post.

It is assumed that every user will forward the post when they see it for the first time, and only L-tier followers will be considered.

Data range
1≤N≤1000,
1≤L≤6,
1≤M[i]≤100,
1≤K≤N
Input example:
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6
Output example:
4
5
Difficulty: medium
Time / space limit: 3s / 64MB
Total number of passes: 327
Total attempts: 817
Source: PAT class a real topic 1076
Algorithm label

thought

Level traversal of the record layer

The first way to write -- your own code
The second way to write -- y total code

Own code

//y total answer also records a writing method of hierarchical traversal!

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1010;
bool g[N][N];
int n, l;
int layer(int root){
    int q[N];
    bool st[N];
    memset(st, 0, sizeof st);//Be sure to re assign the value!!!!
    int hh = 0, tt = -1;
    q[++tt] = root;
    st[root] = true;
    int lay = 1, cnt = 0;
    while(hh <= tt){
        int tail = tt;
        if(lay > l)
            break;
        while(hh <= tail){
            int t = q[hh++];
            for(int j = 1; j <= n; j ++){
                if(g[t][j] && !st[j]){
                    q[++tt] = j;
                    cnt++;
                    st[j] = true;
                }
            }
        }
        lay++;
    }
    return cnt;
}
int main(){
    cin>>n>>l;
    for(int i = 1; i <= n; i ++){
        int m;
        cin>>m;
        for(int j = 0; j < m; j ++){
            int t;
            cin>>t;
            g[t][i] = true;
        }
    }
    int k, q;
    cin>>k;
    for(int i = 0; i < k; i ++){
        cin>>q;
        cout<<layer(q)<<endl;
    }
    
}

y total code

int bfs(int start)
{
    queue<int> q;
    memset(st, 0, sizeof st);

    q.push(start);
    st[start] = true;

    int res = 0;
    for (int step = 0; step < m; step ++ )
    {
        int sz = q.size();
        res += sz;

        for (int i = 0; i < sz; i ++ )
        {
            int t = q.front();
            q.pop();

            for (int j = h[t]; ~j; j = ne[j])
            {
                int k = e[j];
                if (!st[k])
                {
                    st[k] = true;
                    q.push(k);
                }
            }
        }
    }

    return res + q.size() - 1;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/324375/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

First contact

subject

thought

Own code

y total code

Posted by shatner on Mon, 06 Sep 2021 12:33:50 -0700