ACM-ICPC 2018 徐州赛区网络预赛

本文精选了五道算法竞赛题目,涵盖计数问题、游戏策略、概率计算、数论及图形覆盖等多个方面,提供了详细的解题思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

After Incident, a feast is usually held in Hakurei Shrine. This time Reimu asked Kokoro to deliver a Nogaku show during the feast. To enjoy the show, every audience has to wear a Nogaku mask, and seat around as a circle.

There are N guests Reimu serves. Kokoro has 2^k2k masks numbered from 0,1,\cdots,0,1,⋯, 2^k - 12k−1, and every guest wears one of the masks. The masks have dark power of Dark Nogaku, and to prevent guests from being hurt by the power, two guests seating aside must ensure that if their masks are numbered ii and jj , then ii XNOR jj must be positive. (two guests can wear the same mask). XNOR means ~(ii^jj) and every number has kk bits. (11 XNOR 1 = 11=1,00 XNOR 0 = 10=1, 11 XNOR 0 = 00=0)

You may have seen 《A Summer Day's dream》, a doujin Animation of Touhou Project. Things go like the anime, Suika activated her ability, and the feast will loop for infinite times. This really troubles Reimu: to not make her customers feel bored, she must prepare enough numbers of different Nogaku scenes. Reimu find that each time the same guest will seat on the same seat, and She just have to prepare a new scene for a specific mask distribution. Two distribution plans are considered different, if any guest wears different masks.

In order to save faiths for Shrine, Reimu have to calculate that to make guests not bored, how many different Nogaku scenes does Reimu and Kokoro have to prepare. Due to the number may be too large, Reimu only want to get the answer modules 1e9+71e9+7 . Reimu did never attend Terakoya, so she doesn't know how to calculate in module. So Reimu wishes you to help her figure out the answer, and she promises that after you succeed she will give you a balloon as a gift.

Input

First line one number TT , the number of testcases; (T \le 20)(T≤20) .

Next TT lines each contains two numbers, NN and k(0<N, k \le 1e6)k(0<N,k≤1e6) .

Output

For each testcase output one line with a single number of scenes Reimu and Kokoro have to prepare, the answer modules 1e9+71e9+7 .

样例输入复制

2
3 1
4 2

样例输出复制

2
84

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

 

题意:n个人围成一圈,每个人有一个标号(0~2^k-1中的一个数),要求座位相邻的两个人的标号同或之后不能为0,求方案数。

思路:并没有找到规律,然后就瞎搞,可以把点(0~2^k-1)分成三类,起点a,起点a可以到达的除a以外的点b集,a不能到达的点c,n个人相当于包含n个点的环,然后O(n)出最后的a+b上的值就可以了。

#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
ll quick_mod(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%mod;
        b>>=1;
        a = (a*a)%mod;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,k;
        scanf("%lld%lld",&n,&k);
        ll kk = quick_mod(2,k);
        ll a = 1,b =0,c =0;
        n--;
     //  cout<<"k ="<<k<<endl;
     //   cout<<" kk = "<<kk<<endl;
        ll a1,b1,c1;
        while(n--)
        {
            a1 = 0;
            b1 = 0;
            c1 = 0;
            a1=(a1+a)%mod;
            b1=(b1+(a*(kk -2))%mod)%mod;
            
            a1=(a1+b)%mod;
            b1=(b1+(b*(kk-3))%mod)%mod;
            c1=(c1+b)%mod;
            
            b1=(b1+(c*(kk-2))%mod)%mod;
            c1=(c1+c)%mod;
         //   cout<<" a1 = "<<a1<<" b1 = "<<b1<<" c1 = "<<c1<<endl;
            a = a1%mod;
            b = b1%mod;
            c = c1%mod;
         //   cout<<" a = "<<a<<" b = "<<b<<" c = "<<c<<endl;
        }
        printf("%lld\n",((a+b+2*mod)%mod*kk)%mod);
    }
}

B

In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named "Sena" are playing a video game. The game system of this video game is quite unique: in the process of playing this game, you need to constantly face the choice, each time you choose the game will provide 1-31−3 options, the player can only choose one of them. Each option has an effect on a "score" parameter in the game. Some options will increase the score, some options will reduce the score, and some options will change the score to a value multiplied by -1−1 .

That is, if there are three options in a selection, the score will be increased by 11, decreased by 11, or multiplied by -1−1. The score before the selection is 88. Then selecting option 11 will make the score become 99, and selecting option 22 will make the score 77 and select option 33 to make the score -8−8. Note that the score has an upper limit of 100100and a lower limit of -100−100. If the score is 9999 at this time, an option that makes the score +2+2 is selected. After that, the score will change to 100100 and vice versa .

After all the choices have been made, the score will affect the ending of the game. If the score is greater than or equal to a certain value kk, it will enter a good ending; if it is less than or equal to a certain value ll, it will enter the bad ending; if both conditions are not satisfied, it will enter the normal ending. Now, Koutarou and Sena want to play the good endings and the bad endings respectively. They refused to give up each other and finally decided to use the "one person to make a choice" way to play the game, Koutarou first choose. Now assume that they all know the initial score, the impact of each option, and the kk, ll values, and decide to choose in the way that works best for them. (That is, they will try their best to play the ending they want. If it's impossible, they would rather normal ending than the ending their rival wants.)

Koutarou and Sena are playing very happy, but I believe you have seen through the final ending. Now give you the initial score, the kk value, the ll value, and the effect of each option on the score. Can you answer the final ending of the game?

Input

The first line contains four integers n,m,k,ln,m,k,l(1\le n \le 10001≤n≤1000, -100 \le m \le 100−100≤m≤100 , -100 \le l < k \le 100−100≤l<k≤100 ), represents the number of choices, the initial score, the minimum score required to enter a good ending, and the highest score required to enter a bad ending, respectively.

Each of the next nn lines contains three integers a,b,ca,b,c(a\ge 0a≥0 , b\ge0b≥0 ,c=0c=0 or c=1c=1),indicates the options that appear in this selection,in which a=0a=0 means there is no option to increase the score in this selection, a>0a>0means there is an option in this selection to increase the score by aa ; b=0b=0 means there is no option to decrease the score in this selection, b>0b>0 means there is an option in this selection to decrease the score by bb; c=0c=0 means there is no option to multiply the score by -1−1 in this selection , c=1c=1 means there is exactly an option in this selection to multiply the score by -1−1. It is guaranteed that a,b,ca,b,c are not equal to 00 at the same time.

Output

One line contains the final ending of the game. If it will enter a good ending,print "Good Ending"(without quotes); if it will enter a bad ending,print "Bad Ending"(without quotes);otherwise print "Normal Ending"(without quotes).

样例输入1复制

3 -8 5 -5
3 1 1
2 0 1
0 2 1

样例输出1复制

Good Ending

样例输入2复制

3 0 10 3
0 0 1
0 10 1
0 2 1

样例输出2复制

Bad Ending

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

题意:一个数m。在-100到100之间,然后两个人轮流进行一共n次操作,每次操作分为3种(+a,-b,取负(c==1时))可以选一种,先手希望n次操作后结果>=k(good end),后手希望结果<=l(bad end)(l<k),输出最后的结果是什么。

思路:记忆化,从后往前推,这样就可以把后面的结果知道进而知道前面的结果。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[1005][210];
struct node
{
    int a,b,c;
}opt[1005];
void solve(int flag,int&win,int&done,int&lose)
{
    if(flag==1)
        win = 1;
    else if(flag==0)
        done = 1;
    else
        lose = 1;
}
int main()
{
    int n,m,k,l;
    scanf("%d%d%d%d",&n,&m,&k,&l);
    m+=100;k+=100;l+=100;
    for(int i = 1;i<=n;i++)
    {
        scanf("%d%d%d",&opt[i].a,&opt[i].b,&opt[i].c);
    }
    for(int i = 0;i<=l;i++)
        dp[n+1][i] = -1;
    for(int i = l+1;i<k;i++)
        dp[n+1][i] = 0;
    for(int i = k;i<=200;i++)
        dp[n+1][i] = 1;
    for(int i = n;i>=1;i--)
    {
        for(int j = 0;j<=200;j++)
        {
            if(i%2)
            {
                int win = 0,done = 0,lose = 0;
                int tmp;
                if(opt[i].a)
                {
                    tmp = min(200,j+opt[i].a);
                    solve(dp[i+1][tmp],win,done,lose);
                }
                if(opt[i].b)
                {
                    tmp = max(0,j-opt[i].b);
                    solve(dp[i+1][tmp],win,done,lose);
                }
                if(opt[i].c)
                {
                    tmp = 200 - j;
                    solve(dp[i+1][tmp],win,done,lose);
                }
                if(win)dp[i][j] = 1;
                else if(done)dp[i][j] = 0;
                else dp[i][j] = -1;
            }
            else
            {
                int win = 0,done = 0,lose = 0;
                int tmp;
                if(opt[i].a)
                {
                    tmp = min(200,j+opt[i].a);
                    solve(dp[i+1][tmp],lose,done,win);
                }
                if(opt[i].b)
                {
                    tmp = max(0,j-opt[i].b);
                    solve(dp[i+1][tmp],lose,done,win);
                }
                if(opt[i].c)
                {
                    tmp = 200 - j;
                    solve(dp[i+1][tmp],lose,done,win);
                }
                if(win)dp[i][j] = -1;
                else if(done)dp[i][j] = 0;
                else dp[i][j] = 1;
            }
        }
    }
    if(dp[1][m]==1)
        printf("Good Ending\n");
    else if(dp[1][m]==0)
        printf("Normal Ending\n");
    else
        printf("Bad Ending\n");
}

 

C

Morgana is playing a game called cacti lottery. In this game, morgana has a 3 \times 33×3 grid graph, and the graph is filled with 11 ~ 99 , each number appears only once. The game is interesting, he doesn't know some numbers, but there are also some numbers he knows but don't want to tell you.

Now he should choose three grids, these three grids should be in the same column or in the same row or in the diagonal line. Only after this choice, can he know all numbers in the grid graph. Then he sums the three numbers in the grids he chooses, get the reward as follows:

SumReward
610000
736
8720
9360
1080
11252
12108
1372
1454
15180
1672
17180
18119
1936
20360
211080
22144
231800
243600

Then he wants you to predict the expected reward he will get if he is clever enough in the condition that he doesn't want to tell you something he knows.

("He is clever enough" means he will choose the max expected reward row or column or dianonal in the condition that he knows some numbers. And you know that he knows some number, but you don't know what they are exactly. So you should predict his expected reward in your opinion. )

Input

First line contains one integers TT (T \le 100T≤100) represents the number of test cases.

Then each cases contains three lines, giving the 3 \times 33×3 grid graph. '*' means Morgana knows but doesn't want to tell you, '#' means Morgana doesn't know, '0' ~ '9' means the public number that Morgana and you both know.

Output

TT lines, output the answer. If the answer is AA, and your answer is BB. Your answer will be considered as correct if and only if |(A-B)| < 1e-5∣(A−B)∣<1e−5 .

本题答案不唯一,符合要求的答案均正确

样例输入复制

2
123
***
###
12*
45#
78#

样例输出复制

10000
4313.16666667

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

题意:一个3X3的格子,上面有1~9的数字,但是有些数字变为*表示player知道而你不知道,#表示你和player都不知道,现在player横着或竖着或斜着画一条线过三个点,得到对应数字和对应的分数,player足够聪明,求对你来说player的分数期望。

思路:两个dfs,先枚举出*的数字,然后对应地再枚举出#的数字,每个*确定的方案中取期望最大的方案的期望加到结果中,然后对结果除以*的方案数。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int mp[3][3];
bool used[10];
int starx[10],stary[10];
int ux[10],uy[10];
int cnt,star,unk,unkk;
int sz;
double sum[8];
double ans = 0;
double score[25] = 
{
    10000,
    36,
    720,
    360,
    80,
    252,
    108,
    72,
    54,
    180,
    72,
    180,
    119,
    36,
    360,
    1080,
    144,
    1800,
    3600
};
void cntscore()
{
    int x;
    for(int i =0;i<3;i++)
    {
        x = mp[i][0]+mp[i][1]+mp[i][2]-6;
        sum[i]+= score[x];
    }
    for(int i =0;i<3;i++)
    {
        x = mp[0][i]+mp[1][i]+mp[2][i]-6;
        sum[i+3]+= score[x];
    }
    x = mp[0][0]+mp[1][1]+mp[2][2]-6;
    sum[6]+=score[x];
    x = mp[0][2]+mp[1][1]+mp[2][0]-6;
    sum[7]+=score[x];
}
void dfs2(int p)
{
    if(p==unk)
    {
        cntscore();
    }
    else
    {
        for(int i = 1;i<=9;i++)
        {
            if(!used[i])
            {
                used[i] = 1;
                mp[ux[p]][uy[p]] = i;
                dfs2(p+1);
                used[i] = 0;
            }
        }
    }
}
int cas = 0;
void dfs(int p)
{
    if(p==star)
    {
        cas++;
        memset(sum,0,sizeof(sum));
        dfs2(0);
        double maxx = 0;
        for(int i =0 ;i<8;i++)
        {
            maxx = max(maxx,sum[i]);
        }
        ans += maxx/(double)unkk;
   //     for(int i =1;i<=9;i++)if(!used[i])cout<<i<<" ";
    //    cout<<"ans add = "<<maxx/(double)unkk<<endl;
    //    cout<<endl;
    }
    else
    {
        for(int i = 1;i<=9;i++)
        {
            if(!used[i])
            {
                used[i] = 1;
                mp[starx[p]][stary[p]] = i;
                dfs(p+1);
                used[i] = 0;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(used,0,sizeof(used));
        char s[5];
        cnt = 9,star = 0,unk = 0;
        for(int i = 0;i<3;i++)
        {
            scanf("%s",s);
            for(int j = 0;j<3;j++)
            {
                if(s[j]>='0'&&s[j]<='9')
                {
                    mp[i][j] = s[j] - '0';
                    --cnt;
                    used[s[j] - '0'] = 1;
                }
                else if(s[j]=='*')
                {
                    mp[i][j] = -1;
                    starx[star] = i;
                    stary[star] = j;
                    ++star;
                }
                else 
                {
                    mp[i][j] = -2;
                    ux[unk] = i;
                    uy[unk] = j;
                    ++unk;
                }
            }
        }
        unkk = 1;
        for(int i = 1;i<=unk;i++)
        {
            unkk*=i;
        }
        int state = 1;
        for(int i = 1;i<=star;i++)
        {
            state*=(cnt - i +1);
        }
        ans = 0;
        dfs(0);
    //    cout<<"cas = "<<cas<<endl;
    //    cout<<"ans = "<<ans<<endl;
    //    cout<<"state = "<<state<<endl;
        ans/=(double)state;
        printf("%.6lf\n",ans);
    }
}

D

Given a positive integers nn , Mobius function \mu(n)μ(n) is defined as follows:

 

\displaystyle \mu(n) = \begin{cases} 1 &n = 1 \\ (-1)^k & n = p_1p_2\cdots p_k \\ 0 &other \end{cases}μ(n)=⎩⎪⎨⎪⎧​1(−1)k0​n=1n=p1​p2​⋯pk​other​

 

p_i (i = 1, 2, \cdots, k)pi​(i=1,2,⋯,k) are different prime numbers.

Given two integers mm, nn, please calculate \sum_{i = 1}^{m} \mu(in)∑i=1m​μ(in).

Input

One line includes two integers m (1 \le m \le 2e9)m(1≤m≤2e9), n (1 \le n \le 1e12)n(1≤n≤1e12) .

Output

One line includes the answer .

样例输入复制

2 2

样例输出复制

-1

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

参考:https://blog.youkuaiyun.com/ftx456789/article/details/82590044

#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long ll;
const int MAX = 10000010;
ll pri[100];
int pcnt = 0;
ll m,n;

bool prime[MAX];
ll pr[MAX];
int tot;
ll mu[MAX];
map<ll,ll> ma;
void init(){
    memset(prime,0,sizeof(prime));
    tot=0;
    mu[0]=0;mu[1]=1;
    for(int i=2;i<MAX;i++){
        if(!prime[i]){
            pr[tot++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<tot&&pr[j]*i<MAX;j++){
            prime[pr[j]*i]=1;
            if(i%pr[j]==0){
                mu[i*pr[j]]=0;
                break;
            }
            mu[i*pr[j]]=-mu[i];
        }
    }
    for(int i=1;i<MAX;i++) mu[i]+=mu[i-1];
}
ll cal(ll a){
    if(a<MAX) return mu[a];
    if(ma.count(a)) return ma[a];
    ll ans=1;
    for(ll i=2;i<=a;){
        ll x=a/(a/i);
        ans-=cal(a/i)*(x-i+1);
        i=x+1;
    }
    ma[a]=ans;
    return ans;
}
ll dfs(ll m,ll n)
{
    if(m==0)return 0;
    if(n==1)return cal(m);
    for(int i = 0;i<pcnt;i++)
    {
        if(n%pri[i]==0)
        {
            return -dfs(m,n/pri[i])+dfs(m/pri[i],n);
        }
    }
}
int main()
{
    scanf("%lld%lld",&m,&n);
    ll tmp = n;
    bool flag = true;
    for(ll i = 2;i*i<=n;i++)
    {
        if(tmp%i==0)
        {
            int cnt = 0;
            while(tmp%i==0)
            {
                tmp /= i;
                ++cnt;
            }
            if(cnt>1)
            {
                flag = false;
                break;
            }
            pri[pcnt++] = i;
        }
    }
    if(tmp!=1)
    {
        pri[pcnt++] = tmp;
    }
    if(!flag)
    {
        printf("0\n");
        return 0;
    }
    init();
    ma.clear();
    printf("%lld\n",dfs(m,n));
    
}

 

G

There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx , yy ) means the wave is a rectangle whose vertexes are ( 00 , 00 ), ( xx , 00 ), ( 00 , yy ), ( xx , yy ). Every time the wave will wash out the trace of former wave in its range and remain its own trace of ( xx , 00 ) -> ( xx , yy ) and ( 00 , yy ) -> ( xx , yy ). Now the toad on the coast wants to know the total length of trace on the coast after n waves. It's guaranteed that a wave will not cover the other completely.

Input

The first line is the number of waves n(n \le 50000)n(n≤50000).

The next nn lines,each contains two numbers xx yy ,( 0 < x0<x , y \le 10000000y≤10000000 ),the ii-th line means the ii-th second there comes a wave of ( xx , yy ), it's guaranteed that when 1 \le i1≤i , j \le nj≤n ,x_i \le x_jxi​≤xj​ and y_i \le y_jyi​≤yj​ don't set up at the same time.

Output

An Integer stands for the answer.

Hint:

As for the sample input, the answer is 3+3+1+1+1+1=103+3+1+1+1+1=10

样例输入复制

3
1 4
4 1
3 3

样例输出复制

10

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

set+二分。从后往前,二分出第一个x比它小的,那么y必定大于等于它,y同理。

#include<iostream>
#include<stdio.h>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 50010;
set<int>sx,sy;
struct node
{
    int x,y;
}p[maxn];
int main()
{
    sx.clear();
    sy.clear();
    int n;
    scanf("%d",&n);
    for(int i = 0;i<n;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
    }
    ll ans = 0;
    int x,y;
    sx.insert(0);
    sy.insert(0);
    for(int i = n-1;i>=0;i--)
    {
        auto it = sx.lower_bound(p[i].x);
        --it;
        ans += (p[i].x - *it);
        it = sy.lower_bound(p[i].y);
        --it;
        ans += (p[i].y - *it);
        sx.insert(p[i].x);
        sy.insert(p[i].y);
    }   
    printf("%lld\n",ans);
}

J

After the long vacation, the maze designer master has to do his job. A tour company gives him a map which is a rectangle. The map consists of N \times MN×M little squares. That is to say, the height of the rectangle is NN and the width of the rectangle is MM. The master knows exactly how the maze is going to use. The tour company will put a couple in two different squares in the maze and make them seek each other. Of course,the master will not make them find each other easily. The only thing the master does is building some wall between some little squares. He knows in that way, wherever the couple is put, there is only one path between them. It is not a difficult thing for him, but he is a considerate man. He also knows that the cost of building every wall between two adjacent squares is different(Nobody knows the reason). As a result, he designs the maze to make the tour company spend the least money to build it.

Now, here's your part. The tour company knows you're the apprentice of the master, so they give you a task. you're given QQ qustions which contain the information of where the couple will be put. You need to figure out the length of the shortest path between them.

However,the master doesn't tell you how he designs the maze, but he believes that you, the best student of himself, know the way. So he goes on vacation again.

Input

The first line of the input contains two integers NN and MM (1 \le N,M \le 5001≤N,M≤500), giving the number of rows and columns of the maze.

The next N \times MN×M lines of the input give the information of every little square in the maze, and their coordinates are in order of (1,1)(1,1) , (1,2)(1,2) \cdots⋯ (1,M)(1,M) , (2,1)(2,1) , (2,2)(2,2) , \cdots⋯ , (2,M)(2,M) , \cdots⋯ ,(N,M)(N,M).

Each line contains two characters DD and RR and two integers aa , bb (0 \le a,b \le 20000000000≤a,b≤2000000000 ), aa is the cost of building the wall between it and its lower adjacent square, and bb is the cost of building the wall between it and its right adjacent square. If the side is boundary, the lacking path will be replaced with X 00.

The next line contains an integer QQ (1 \le Q \le 1000001≤Q≤100000 ), which represents the number of questions.

The next QQ lines gives four integers, x_1x1​, y_1y1​, x_2x2​, y_2y2​ ( 1 \le x_11≤x1​ , x_2 \le Nx2​≤N , 1 \le y_11≤y1​ , y_2 \le My2​≤M ), which represent two squares and their coordinate are (x_1x1​ , y_1y1​) and (x_2x2​ , y_2y2​).

(xx,yy) means row xx and column yy.

It is guaranteed that there is only one kind of maze.

Output

For each question, output one line with one integer which represents the length of the shortest path between two given squares.

样例输入复制

3 3
D 1 R 9
D 7 R 8
D 4 X 0
D 2 R 6
D 12 R 5
D 3 X 0
X 0 R 10
X 0 R 11
X 0 X 0
3
1 1 3 3
1 2 3 2
2 2 3 1

样例输出复制

4
2
2

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

最大生成树+LCA

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=250010;//最大点数
const int MAXM=500010;//最大边数
int F[MAXN];//并查集使用
int f[MAXN][25], deep[MAXN];
vector <int> vec[MAXN];
struct Edge
{
    int u,v,w;
}edge[MAXM];//储存边的信息,包括起点/终点/权值
 
int tol;//边数,加边前赋值为0
 
void addedge(int u,int v,int w)
{
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol++].w=w;
}
 
bool cmp(Edge a,Edge b)//排序函数,边按照权值从小到大排序
{
    return a.w>b.w;
}
 
int Find(int x)
{
    if(F[x]==-1)
        return x;
    else
        return F[x]=Find(F[x]);
}
 
void Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
    memset(F,-1,sizeof(F));
    sort(edge,edge+tol,cmp);
    int cnt=0;//计算加入的边数
    //int ans=0;
    for(int i=0;i<tol;i++)
    {
        int u=edge[i].u;
        int v=edge[i].v;
        int w=edge[i].w;
        int t1=Find(u);
        int t2=Find(v);
        if(t1!=t2)
        {
        //    ans+=w;
            F[t1]=t2;
            cnt++;
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        if(cnt==n-1)
            break;
    }
}


void dfs(int u)
{
    int i, v;
    deep[u] = deep[f[u][0]] + 1;
    for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
    for(i = 0; i < vec[u].size(); i++)
    {
        v = vec[u][i];
        if(!deep[v]) f[v][0] = u, dfs(v);
    }
}

int lca(int x, int y)
{
    int i;
    if(deep[x] < deep[y]) swap(x, y);
    for(i = 20; i >= 0; i--)
        if(deep[f[x][i]] >= deep[y])
            x = f[x][i];
    if(x == y) return x;
    for(i = 20; i >= 0; i--)
        if(f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i =0;i<=n*m;i++)
    {
        vec[i].clear();
    }
    char s1[3],s2[3];
    int a,b;
    for(int i =1;i<=n*m;i++)
    {
        scanf("%s%d%s%d",s1,&a,s2,&b);
        if(s1[0]!='X')
        {
            addedge(i,i+m,a);
        }
        if(s2[0]!='X')
        {
            addedge(i,i+1,b);
        }
    }
    Kruskal(n*m);
    dfs(1);
    int q;
    scanf("%d",&q);
    int x1,y1,x2,y2;
    while(q--)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        a = (x1-1)*m+y1;
        b = (x2-1)*m+y2;
        printf("%d\n",deep[a] + deep[b] - deep[lca(a,b)]*2);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值