1. 程式人生 > 其它 >pat甲級圖的判斷

pat甲級圖的判斷

圖的判斷問題一般基於是給定一個場景或者是關於一個圖的定義問題,然後輸入一張圖,給定一組資料要求判斷這組資料是否是滿足這個圖的相關定義

比如給定一個哈密頓迴路或者是最大團最小團問題或者是拓撲排序的問題

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805500414115840

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5
const int N=1e3+10; 6 int n,m,k; 7 int g[N][N]; 8 //vector<int>g[N]; 9 int cnt; 10 bool vis[N]; 11 int ch; 12 void dfs(int u) 13 { 14 if(u==ch) 15 return ; 16 vis[u]=true; 17 for(int v=1;v<=u;v++) 18 { 19 if(!vis[v]&&g[u][v]) 20 { 21 dfs(v);
22 } 23 } 24 25 } 26 signed main() 27 { 28 IOS; 29 cin>>n>>m>>k; 30 for(int i=0;i<m;i++) 31 { 32 int s,t; 33 cin>>s>>t; 34 g[s][t]++; 35 g[t][s]++; 36 //g[s].push_back(t); 37 //g[t].push_back(s);
38 } 39 for(int i=0;i<k;i++) 40 { 41 cin>>ch; 42 cnt=0; 43 memset(vis,0,sizeof(vis)); 44 for(int j=1;j<=n;j++) 45 { 46 if(j!=ch&&!vis[j]) 47 { 48 dfs(j); 49 cnt++; 50 } 51 } 52 cout<<cnt-1<<endl; 53 } 54 return 0; 55 }

鄰接矩陣做法;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=1e3+10;
 6 int n,m,k;
 7 int g[N][N];
 8 //vector<int>g[N];
 9 int cnt;
10 bool vis[N];
11 int ch;
12 void dfs(int u)
13 {
14     if(u==ch)
15     return ;
16     vis[u]=true;
17     for(int v=1;v<=u;v++)
18     {
19         if(!vis[v]&&g[u][v])
20         {
21             dfs(v);
22         }
23     }
24     
25 }
26 signed main()
27 {
28     IOS;
29     cin>>n>>m>>k;
30        for(int i=0;i<m;i++)
31     {
32         int s,t;
33         cin>>s>>t;
34         g[s][t]++;
35         g[t][s]++;
36         //g[s].push_back(t);
37         //g[t].push_back(s);
38     }
39      for(int i=0;i<k;i++)
40      {
41          cin>>ch;
42          cnt=0;
43          memset(vis,0,sizeof(vis));
44          for(int j=1;j<=n;j++)
45          {
46              if(j!=ch&&!vis[j])
47              {
48                  dfs(j);
49                  cnt++;
50              }
51          }
52          cout<<cnt-1<<endl;
53      }
54     return 0;
55 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805351814119424

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long 
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=210;
 6 int g[N][N];
 7 int a[N];
 8 int n,m;
 9 int q;
10 int tmp;
11 set<int>qs;
12 signed main()
13 {
14     IOS;
15     cin>>n>>m;
16     int s,t;
17     for(int i=1;i<=m;i++)
18     {
19         cin>>s>>t;
20         g[s][t]=g[t][s]=1;
21     }
22     cin>>q;
23     while(q--)
24     {
25         bool flag1=true;
26         bool flag2=true;
27         qs.clear();
28         memset(a,0,sizeof(a));
29         cin>>tmp;
30         for(int i=1;i<=tmp;i++)
31         {
32             cin>>a[i];
33             qs.insert(a[i]);
34         }
35         if(tmp-1!=n||qs.size()!=n||a[1]!=a[tmp])
36         {
37             flag1=false;
38         }
39         for(int i=1;i<tmp;i++)
40         {
41             if(g[a[i]][a[i+1]]==0)
42             {
43                   flag2=false;
44                   break;
45             }
46         }
47         if(flag1&&flag2)
48         {
49             cout<<"YES"<<endl;
50         }
51         else{
52             cout<<"NO"<<endl;
53         }
54     }
55     return 0;
56 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805349851185152

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=510;
 6 vector<int>g[N];
 7 int n,m;
 8 int cnt;
 9 int x;
10 bool vis[N];
11 void dfs(int u)
12 {
13     vis[u]=true;
14     cnt++;
15     for(int v=0;v<g[u].size();v++)
16     {
17         if(!vis[g[u][v]])
18         {
19             dfs(g[u][v]);
20         }
21     }
22 }
23 signed main()
24 {
25     IOS;
26     cin>>n>>m;
27     int s,t;
28     for(int i=0;i<m;i++)
29     {
30         cin>>s>>t;
31         g[s].push_back(t);
32         g[t].push_back(s);
33     }
34        for(int i=1;i<=n;i++)
35        {
36            if(g[i].size()%2==0)
37            {
38                x++;
39            }
40            cout<<g[i].size();
41            if(i<n)
42            cout<<" ";
43        }
44        dfs(1);
45        cout<<endl;
46        if(cnt==n&&x==n)
47        {
48            cout<<"Eulerian";
49        }
50        else if(cnt==n&&x==n-2)
51        {
52            cout<<"Semi-Eulerian";
53        }
54        else
55        {
56            cout<<"Non-Eulerian";
57        }
58     return 0;
59 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805343979159552

 1 //主要是敗在讀題上其實
 2 //這道題的意思區別團和最大團
 3 //所謂團就是給定的一組序列的點都是一一相鄰的
 4 //最大團是不能在找一個點來加入集合序列形成最大團
 5 //換言之就是在所有的點中不存在一個點在和集合中的點一一相鄰,也就是如果除去集合中的點
 6 //如果在存在一個點與集合中的點一一相鄰那他就不是最大團
 7 //所以說本題的做法是建一個hash來儲存不在集合中的點
 8 //先遍歷集合是否是團
 9 //在遍歷沒有在集合中的點是否和集合中的點一一相鄰
10 #include<bits/stdc++.h>
11 using namespace std;
12 #define int long long 
13 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
14 const int N=210;
15 int g[N][N];
16 int n,m;
17 int q;
18 int k;
19 signed main()
20 {
21     IOS;
22     cin>>n>>m;
23     int s,t;
24     for(int i=1;i<=m;i++)
25     {
26         cin>>s>>t;
27         g[s][t]=g[t][s]=1;
28     }
29     cin>>q;
30     while(q--)
31     {
32         int a[N]={0};
33         bool flag1=true;
34         bool flag2=true;
35         int hasha[N]={0};
36         cin>>k;
37         for(int i=1;i<=k;i++)
38         {
39             cin>>a[i];
40             hasha[a[i]]=1;
41         }
42         for(int i=1;i<=k;i++)
43         {
44             if(!flag1)
45                 break;
46             for(int j=i+1;j<=k;j++)
47             {
48                 if(!g[a[i]][a[j]])
49                 {
50                     flag1=false;
51                     cout<<"Not a Clique"<<endl;
52                     break;
53                 }
54             }
55         }
56         if(!flag1)
57             continue;
58         for(int i=1;i<=n;i++)
59         {
60             if(!hasha[i])
61             {
62                 for(int j=1;j<=k;j++)
63                 {
64                     if(!g[i][a[j]])
65                         break;
66                     if(j==k)
67                         flag2=false;
68                 }
69             }
70             if(!flag2)
71             {
72                 cout<<"Not Maximal"<<endl;
73                 break;
74             }
75         }
76         if(flag2)
77             cout<<"Yes"<<endl;
78     }
79     return 0;
80 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805346428633088

 1 //首先解讀題意
 2 //本題的大意是圖中的邊至少和給定集合中的一個點相關聯,則稱這個圖為點覆蓋圖
 3 //本題就是判斷是否是點覆蓋問題
 4 //需要注意的細節
 5 //g[i][j]表示i點和j邊相關聯
 6 //存一個雜湊表表示這個點和這個邊相關聯
 7 //然後在遍歷所有的邊,如果有!hasha[i]就說明對於這條邊來講沒有一個點出自集合中,就判斷為No
 8 //否則判斷為Yes
 9 #include<bits/stdc++.h>
10 using namespace std;
11 #define int long long 
12 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
13 const int N=1e4+10;
14 vector<int>g[N];
15 int n,m,q;
16 int k;
17 signed main()
18 {
19     IOS;
20     cin>>n>>m;
21     int s,t;
22     for(int i=0;i<m;i++)
23     {
24         cin>>s>>t;
25         g[s].push_back(i);
26         g[t].push_back(i);
27     }
28     cin>>q;
29     while(q--)
30     {
31         bool flag=true;
32         vector<int>hasha(m,0);
33         cin>>k;
34         int tmp;
35         for(int i=0;i<k;i++)
36         {
37             cin>>tmp;
38             for(int j=0;j<g[tmp].size();j++)
39             {
40                 hasha[g[tmp][j]]=1;
41             }
42         }
43         for(int i=0;i<m;i++)
44         {
45             if(!hasha[i])
46             {
47                 cout<<"No"<<endl;
48                 flag=false;
49                 break;
50             }
51         }
52         if(flag)
53         cout<<"Yes"<<endl;
54     }
55     return 0;
56 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805343043829760

 1 //本題需要注意的點
 2 //這道題要求判斷是否是拓撲序列
 3 //那我們就可以依照定義來判斷,先入隊的是入度為0的節點, 然後將相鄰節點的入度減一,再將當前入隊的
 4 //的節點出隊,再將臨界點入度為0的點入隊
 5 //而對於本題來講,在進行加入臨界點和入度統計後,我們依次輸入給定的節點,如果輸入的節點入度不為0
 6 //那他就不是拓撲序列,如果是,就將其臨界點的入度也減一,最後判斷flag的值
 7 //需要注意輸出的格式
 8 #include<bits/stdc++.h>
 9 using namespace std;
10 #define int long long 
11 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
12 const int N=1e3+10;
13 vector<int>g[N];
14 int n,m,k;
15 int tmp;
16 int in[N];
17 bool geshi;
18 signed main()
19 {
20     IOS;
21     cin>>n>>m;
22     int s,t;
23     for(int i=1;i<=m;i++)
24     {
25         cin>>s>>t;
26         g[s].push_back(t);
27         in[t]++;
28         
29     }
30     cin>>k;
31     for(int i=0;i<k;i++)
32     {
33         bool flag=true;
34         vector<int>rd(in,in+1+n);
35         for(int j=0;j<n;j++)
36         {
37             cin>>tmp;
38             if(rd[tmp]!=0)
39             {
40                 flag=false;
41                 //break;
42             }
43             for(int k=0;k<g[tmp].size();k++)
44             {
45                 rd[g[tmp][k]]--;
46             }
47         }
48         if(flag)
49         continue;
50         if(geshi)
51         cout<<" "<<i;
52         else
53         cout<<i;
54         geshi=true;
55     }
56     return 0;
57 }

https://pintia.cn/problem-sets/994805342720868352/exam/problems/1038430013544464384

 1 //題目大意,要求判斷給定的序列是否是滿足最簡TSP圖,或者是TSP圖,或者不是
 2 //最簡TSP就是不僅訪問每個點並且首位相連,除此之外還滿足k=n+1即訪問原點兩次
 3 //這道題其實就根據題意判斷每個序號的序列是否滿足就可以了
 4 //如果這個圖有任意兩個連續的序列點是不相鄰的,那他的距離就是NA
 5 //其餘的在輸入的時候將其放在集合裡,然後判斷相鄰性和累加距離
 6 //然後判斷就可以了
 7 #include<bits/stdc++.h>
 8 using namespace std;
 9 #define int long long
10 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
11 const int INF=0x3f3f3f3f;
12 const int N=210;
13 int g[N][N];
14 int n,m;
15 int q;
16 int index=-1;
17 int ans=INF;
18 void solved(int id)
19 {
20     int sum=0;
21     set<int>s;
22     bool flag=true;
23     int k;
24     vector<int>a(N);
25     cin>>k;
26     for(int i=1;i<=k;i++)
27     {
28         cin>>a[i];
29         s.insert(a[i]);
30     }
31     for(int i=1;i<k;i++)
32     {
33         if(!g[a[i]][a[i+1]])
34             flag=false;
35         sum+=g[a[i]][a[i+1]];
36     }
37     if(!flag)
38     {
39         printf("Path %lld: NA (Not a TS cycle)\n",id);
40         return ;
41     }
42     if(a[1]!=a[k]||s.size()!=n)
43     {
44         printf("Path %lld: %lld (Not a TS cycle)\n",id,sum);
45         return ;
46     }
47     if(k!=n+1)
48     {
49         printf("Path %lld: %lld (TS cycle)\n",id,sum);
50            if(ans>sum)
51         {
52             ans=sum;
53             index=id;
54         }
55     }
56     else{
57        printf("Path %lld: %lld (TS simple cycle)\n",id,sum);
58         if(ans>sum)
59         {
60             ans=sum;
61             index=id;
62         }
63     }
64 }
65 signed main()
66 {
67   //  IOS;
68     cin>>n>>m;
69     int s,t,d;
70     for(int i=1;i<=m;i++)
71     {
72         cin>>s>>t>>d;
73         g[s][t]=g[t][s]=d;
74     }
75     cin>>q;
76     for(int i=1;i<=q;i++)
77     {
78         solved(i);
79     }
80     cout<<"Shortest Dist"<<"("<<index<<")"<<" = "<<ans;
81     return 0;
82 }