图论2

A.同化

时间限制: 1000ms
空间限制: 524288kB

题目描述

古人云:“近朱者赤近墨者黑”。这句话是很有道理的。这不鱼大大和一群苦命打工仔被安排进厂拧螺丝了。
进厂第一天,每个人拧螺丝的动力k都是不同且十分高涨的。但是当大家坐在一起后会聊天偷懒,导致第二天时,每个人的拧螺丝动力变为昨天自己和四周人拧螺丝动力的最大公约数。当拧螺丝动力掉到1时,鱼大大就会跑路。
厂子的老板会对鱼大大这群打工仔安排拧螺丝的位置,可以简单看成是一个N*M的矩阵。现有工厂座位安排表,鱼大大坐在第X行第Y列,问最少几天后鱼大大就会跑路
【题意简化】
有一个N*M的矩阵,对其进行变换,将矩阵中的每一个元素变为其上下左右及自身(不存在则忽略)的最大公约数。问aXY多少次变幻后会变成1.

输入格式

第一行两个整数N,M,表示矩阵的行数和列数。
接下来 N 行,每行 M 个整数,第 i 行第 j 列的整数 ai,j 表示为该位置的人第一天拧螺丝的动力。
接下来一行两个整数 X,Y,表示鱼大大的位置。

输出格式

一行一个整数表示鱼大大第几天会跑路
(若是动力永远不掉到1,则为不会跑路,输出-1)

样例

Input 1

2 2
2 2
1 2
2 1

Output 1

0

Input 2

2 2
2 2
2 2
1 1

Output 2

-1

Input 3

3 3
3 2 3
2 3 2
3 2 3
2 2

Output 3

1

数据范围

2 ≤ N,M ≤ 1000;
1 ≤ aij ≤ 100000;
保证X,Y合法,即鱼大大位置肯定在矩阵范围中

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e3+10;
 4 struct node{
 5     int x,y,val;
 6 };
 7 int ar[N][N],n,m,x,y;
 8 bool st[N][N];
 9 int res=-1;
10 int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
11 inline void bfs(int x,int y){
12     queue<node> q;
13     q.push({x,y,0});
14     st[x][y]=true;
15     if(ar[x][y]<=1){
16         res=0;
17         return;
18     }
19     while(!q.empty()){
20         node t=q.front();
21         q.pop();
22         int a=t.x,b=t.y,c=t.val;
23         if(ar[a][b]<=1){
24             res=c;
25             return;
26         }
27         for(int i=0;i<4;i++){
28             int _x=a+dx[i],_y=b+dy[i];
29             if(_x>=1&&_x<=n&&_y>=1&&_y<=m&&!st[_x][_y]){
30                 st[_x][_y]=true;
31                 ar[_x][_y]=__gcd(ar[a][b],ar[_x][_y]);
32                 q.push({_x,_y,c+1});
33             }
34         }
35     }
36 }
37 inline void solve(){
38     cin>>n>>m;
39     for(int i=1;i<=n;i++){
40         for(int j=1;j<=m;j++){
41             cin>>ar[i][j];
42         }
43     }
44     cin>>x>>y;
45     bfs(x,y);
46     cout<<res<<"\n";
47 }
48 signed main(){
49     solve();
50     return 0;
51 }
AC Code

 

B.树论图论差不多嘛

时间限制: 1000ms
空间限制: 524288kB

题目描述

给定一棵 n 个点的树,现在要按照以下方法画出这棵树:

0. 画 1 号点。

步骤0执行完成后,继续执行 1。

1. 按输入顺序将所有边遍历一遍。对于遍历到的每条边 (u,v),如果 u,v 中有一个点已经画出来了,那么就把另一个点也画出来,并且画出 (u,v) 这条边。

步骤1执行完成后,继续执行 2。

2. 如果所有点都画出来了,那就结束;否则,重新执行 1。

问 1 步骤总共执行多少次。

 

输入第一行一个整数 T ,表示数据组数。

每组数据第一行一个整数 n,接下来 n-1 行输入树的边。

对于每组数据,输出一行一个整数表示答案。

输入样例

2 6 4 5 1 3 1 2 3 4 1 6 7 5 6 2 4 2 7 1 3 1 2 4 5

输出样例

2 3

数据范围

对于50%的数据,0<T10^4,0<n2×10^3,n2×10^3

对于100%的数据,0<T10^4,0<n2×10^5,n2×10^5

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e5+10;
 4 vector<pair<int,int> > q[N];
 5 bool st[N];
 6 int dist[N];
 7 int n;
 8 inline void dfs(int x,int fa){
 9     st[x]=true;
10     for(auto[u,v]:q[x]){
11         if(!st[u]){
12             dist[u]=(v<fa)+dist[x];
13             dfs(u,v);
14         }
15     }
16     return;
17 }
18 inline void solve(){
19     cin>>n;
20     for(int i=1;i<=n;i++){
21         st[i]=false;
22         q[i].clear();
23     }
24     for(int i=1;i<n;i++){
25         int a,b;
26         cin>>a>>b;
27         q[a].push_back({b,i});
28         q[b].push_back({a,i});
29     }
30     dist[1]=0;
31     dfs(1,n);
32     int res=0;
33     for(int i=1;i<=n;i++) res=max(res,dist[i]);
34     cout<<res<<"\n";
35 }
36 signed main(){
37     int _;
38     cin>>_;
39     while(_--){
40         solve();
41     }
42     return 0;
43 }
AC Code
posted @ 2024-01-06 10:50  Tinx  阅读(105)  评论(0)    收藏  举报