数据结构与算法A实验六图论
7-1 列出连通集 (25 分)
#include<bits/stdc++.h>
#define eb emplace_back
#define ll long long
const int N = 2e5 + 10;
const int M = 111;
using namespace std;
int n,e; // 点数、边数
int mp[M][M]; // 建图
bool st[N]; // 标记数组
void DFS(int x){ // DFS
st[x]=1; // 当前点已走过
cout<<" "<<x; // 输出
for(int i=0;i<n;i++){ // 遍历能到达的边
if(!st[i]&&mp[x][i]) DFS(i);
}
}
void BFS(int x){ // BFS
queue<int>q; //定义队列
q.push(x); // 当前点入队
st[x]=1; //当前点已走过
while(q.size()){
auto t=q.front(); //取队头
q.pop();
cout<<" "<<t; // 输出
for(int i=0;i<n;i++){ // 遍历能到达的边
if(!st[i]&&mp[t][i]){
st[i]=1;
q.push(i);
}
}
}
}
inline void solve(){
cin>>n>>e;
for(int i=1;i<=e;i++){ // 建图
int u,v;
cin>>u>>v;
mp[u][v]=mp[v][u]=1;
}
for(int i=0;i<n;i++){ // 输出DFS结果
if(!st[i]){
cout<<"{";
DFS(i);
cout<<" }\n";
}
}
memset(st,0,sizeof st); // 清空st标记数组
for(int i=0;i<n;i++){ // 输出BFS结果
if(!st[i]){
cout<<"{";
BFS(i);
cout<<" }\n";
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-2 哈利·波特的考试 (25 分)
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
using namespace std;
int n,m; // 点数、边数
int g[111][111]; // 存图
void Floyd(){ // Floyd求最短路(多源汇最短路)
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
}
inline void solve(){
cin>>n>>m;
int u,v,k;
for(int i=1;i<=n;i++){ // 初始化
for(int j=1;j<=n;j++){
if(i==j) g[i][j]=0;
else g[i][j]=inf;
}
}
while(m--){ // 建图
cin>>u>>v>>k;
g[u][v]=g[v][u]=k;
}
Floyd(); // Floyd求最短路
int id=0,minn=inf;
for(int i=1;i<=n;i++){
int maxn=0;
for(int j=1;j<=n;j++){
maxn=max(maxn,g[i][j]); // 每个动物需要的最大值
}
if(minn>maxn){ // 最大消耗值的最小值
minn=maxn;
id=i;
}
}
if(id) cout<<id<<" "<<minn<<endl;
else cout<<"0"<<endl;
}
int main(){
solve();
return 0;
}
7-3 旅游规划 (25 分)
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
const int M = 511;
using namespace std;
int n,m,s,e; // 点数、边数、起点、终点
int w[M][M]; // 存距离
int p[M][M]; // 存话费
void Floyd(){ // Floyd求最短路
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(w[i][j]>w[i][k]+w[k][j]){
w[i][j]=w[i][k]+w[k][j];
p[i][j]=p[i][k]+p[k][j];
}else if(w[i][j]==w[i][k]+w[k][j]){
if(p[i][j]>p[i][k]+p[k][j]){
p[i][j]=p[i][k]+p[k][j];
}
}
}
}
}
cout<<w[s][e]<<" "<<p[s][e]<<endl; // 输出答案
}
inline void solve(){
cin>>n>>m>>s>>e;
memset(w,0x3f,sizeof w); // 距离初始化
memset(p,0x3f,sizeof p); // 花费初始化
for(int i=0;i<n;i++) w[i][i]=p[i][i]=0;
while(m--){ // 建图
int u,v,W,P;
cin>>u>>v>>W>>P;
w[u][v]=w[v][u]=W;
p[u][v]=p[v][u]=P;
}
Floyd();
}
int main(){
solve();
return 0;
}
7-4 公路村村通 (30 分)
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
const int M = 3111;
using namespace std;
int n,m;
int res=0;
int vis[N];
struct node{ // 结构体存图
int u,v,w;
}dp[N];
bool cmp(node x,node y){ //排序规则
return x.w<y.w;
}
void init(){ // 初始化
for(int i=1;i<=M;i++) vis[i]=i;
}
int Find(int x){ // 并查集
if(x!=vis[x]) vis[x]=Find(vis[x]);
return vis[x];
}
bool Merge(int x,int y){ // 合并
int xx=Find(x);
int yy=Find(y);
if(xx!=yy){
vis[xx]=yy;
return 0;
}
return 1;
}
void Kruskal(){ // Kruskal构造最小生成树
int tot=0;
for(int i=1;i<=m;i++){
if(tot==n-1) break;
if(!Merge(dp[i].u,dp[i].v)){
res+=dp[i].w;
tot++;
}
}
if(tot==n-1) cout<<res<<endl; // 联通输出结果
else cout<<-1<<endl; // 不连通输出-1
}
inline void solve(){
cin>>n>>m;
init(); // 初始化
for(int i=1;i<=m;i++) cin>>dp[i].u>>dp[i].v>>dp[i].w; // 建图
sort(dp+1,dp+1+m,cmp); // 排序
Kruskal(); // Kruskal构建最小生成树
}
int main(){
solve();
return 0;
}
7-5 任务调度的合理性 (25 分)
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
using namespace std;
int n;
int in[N];
int mp[111][111];
bool Topo(){ // 拓扑排序判断合法性
queue<int>q;
for(int i=1;i<=n;i++){ // 入度为0入队
if(!in[i]) q.push(i);
}
int cnt=0; // 计数
while(q.size()){
auto t=q.front(); // 取队首
q.pop(); // 出队
cnt++;
in[t]--; // 入度变为-1
for(int i=1;i<=n;i++){
if(mp[t][i]){
in[i]--; //入度-1
if(!in[i]) q.push(i); // 入度为0入队
}
}
}
if(cnt==n) return 1; // 合法
else return 0; //不合法
}
inline void solve(){
cin>>n; // 输入点数
for(int i=1;i<=n;i++){ // 建图
int k;
cin>>k;
if(k){
while(k--){
int x;
cin>>x;
mp[i][x]=1; // 连边
in[x]++; // 到达点入度+1
}
}
}
if(Topo()) cout<<1<<endl;
else cout<<0<<endl;
}
int main(){
solve();
return 0;
}
本题测试点(慎用)

7-6 家庭房产 (25 分)
#include<bits/stdc++.h>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(auto i=a;i<=b;++i)
const int N = 1e5 + 10;
const int M = 555;
using namespace std;
struct data{
int id;
int fa;
int mo;
int num;
int area;
int cp[M];
}dp[N];
struct node{
int id;
int peo;
double num;
double area;
bool flag=0;
}mp[N];
int fat[N];
bool vis[N];
int Find(int x){ // 并查集
if(fat[x]!=x) fat[x]=Find(fat[x]);
return fat[x];
}
void Merge(int u,int v){ // 合并
int x=Find(u);
int y=Find(v);
if(x>y) fat[x]=y;
else if(x<y) fat[y]=x;
}
bool cmp(node x,node y){ // 排序
if(x.area!=y.area) return x.area>y.area;
else return x.id<y.id;
}
void init(int n){ // 初始化
rep(i,0,10000) fat[i]=i;
}
void solve(){
int n;
int k;
int tot=0;
cin>>n;
init(n);
rep(i,0,n-1){
cin>>dp[i].id>>dp[i].fa>>dp[i].mo>>k;
vis[dp[i].id]=1;
if(dp[i].fa!=-1){
vis[dp[i].fa]=1;
Merge(dp[i].fa,dp[i].id);
}
if(dp[i].mo!=-1){
vis[dp[i].mo]=1;
Merge(dp[i].mo,dp[i].id);
}
rep(j,0,k-1){
cin>>dp[i].cp[j];
vis[dp[i].cp[j]]=1;
Merge(dp[i].cp[j],dp[i].id);
}
cin>>dp[i].num>>dp[i].area;
}
rep(i,0,n-1){
int id=Find(dp[i].id);
mp[id].id=id;
mp[id].num+=dp[i].num;
mp[id].area+=dp[i].area;
mp[id].flag=1;
}
rep(i,0,10000){
if(vis[i]) mp[Find(i)].peo++;
if(mp[i].flag) tot++;
}
rep(i,0,10000){
if(mp[i].flag){
mp[i].num=(double)(mp[i].num*1.0/mp[i].peo);
mp[i].area=(double)(mp[i].area*1.0/mp[i].peo);
}
}
sort(mp,mp+10000,cmp);
cout<<tot<<endl;
rep(i,0,tot-1){
printf("%04d %d %.3f %.3f\n",mp[i].id,mp[i].peo,mp[i].num,mp[i].area);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-7 最短工期 (25 分)
#include<bits/stdc++.h>
#define PII pair<int,int>
#define eb emplace_back
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
using namespace std;
int n,m;
int in[N];
int res[N];
int dist[N];
int tot=0;
vector<PII>g[N];
void topo(){ // 拓扑求关键路径
queue<int>q;
for(int i=0;i<n;i++){
if(!in[i]) q.push(i);
}
while(q.size()){
auto u=q.front();
q.pop();
res[tot++]=u;
for(auto i:g[u]){
auto v=i.x,w=i.y;
in[v]--;
if(!in[v]) q.push(v);
if(dist[v]<dist[u]+w) dist[v]=dist[u]+w;
}
}
}
inline void solve(){
cin>>n>>m;
while(m--){
int u,v,w;
cin>>u>>v>>w;
g[u].eb(PII{v,w}); // 存图
in[v]++; // 入度++
}
topo();
if(tot==n){
int maxn=0;
for(int i=0;i<n;i++) maxn=max(maxn,dist[i]);
cout<<maxn<<endl;
}else cout<<"Impossible"<<endl;
}
int main(){
solve();
return 0;
}
7-8 路径判断 (20 分)
#include<bits/stdc++.h>
#define eb emplace_back
#define ll long long
const int N = 2e5 + 10;
const int M = 111;
using namespace std;
int n,m; // 点数、边数
int s,e; // 起始点
int mp[M][M]; // 存图
bool st[M]; // 标记数组
bool BFS(){ // BFS判断是否有路径
queue<int>q;
q.push(s);
while(q.size()){
auto x=q.front();
q.pop();
st[x]=1;
if(x==e) return 1;
for(int i=0;i<n;i++){
if(!st[i]&&mp[x][i]){
q.push(i);
}
}
}
return 0;
}
inline void solve(){
cin>>n>>m;
int u,v;
while(m--){ // 建图
cin>>u>>v;
mp[u][v]=mp[v][u]=1;
}
cin>>s>>e; // 输入起始点
if(BFS()) cout<<"There is a path between "<<s<<" and "<<e<<"."<<endl; // 若有路径
else cout<<"There is no path between "<<s<<" and "<<e<<"."<<endl; // 无路径
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-9 最短路径 (20 分)
#include<bits/stdc++.h>
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define inf 0x3f3f3f3f
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
const int N = 11;
using namespace std;
int n,m,s,ed; // 点数、边数、起点、终点
int g[N][N]; // 存边
void Floyd(){ // Floyd 求最短路
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
}
inline void solve(){
cin>>n>>m;
mem(g,inf);
while(m--){ // 存边
int u,v;
cin>>u>>v;
g[u][v]=g[v][u]=1;
}
cin>>s>>ed;
Floyd();
if(s==ed) cout<<"The length of the shortest path between "<<s<<" and "<<ed<<" is "<<0<<"."<<endl;
else if(g[s][ed]!=inf) cout<<"The length of the shortest path between "<<s<<" and "<<ed<<" is "<<g[s][ed]<<"."<<endl;
else cout<<"There is no path between "<<s<<" and "<<ed<<"."<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-10 邻接矩阵表示法创建无向图 (20 分)
#include<bits/stdc++.h>
#define eb emplace_back
#define ll long long
const int N = 2e5 + 10;
const int M = 111;
using namespace std;
int du[N]; // 记录度
inline void solve(){
int n,m;
cin>>n>>m;
string s;
cin>>s;
char u,v;
while(m--){
cin>>u>>v;
//cout<<u<<" "<<v<<"*"<<endl;
du[u-'A']++; // 度++
du[v-'A']++; // 度++
}
for(int i=0;i<s.size();i++){ // 输出
if(i) cout<<" ";
cout<<du[s[i]-'A'];
}
cout<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-11 邻接表创建无向图 (20 分)
#include<bits/stdc++.h>
#define eb emplace_back
#define ll long long
const int N = 2e5 + 10;
const int M = 111;
using namespace std;
int du[N]; // 记录度
inline void solve(){
int n,m;
cin>>n>>m;
string s;
cin>>s;
char u,v;
while(m--){
cin>>u>>v;
//cout<<u<<" "<<v<<"*"<<endl;
du[u-'A']++; // 度++
du[v-'A']++; // 度++
}
for(int i=0;i<s.size();i++){ // 输出
if(i) cout<<" ";
cout<<du[s[i]-'A'];
}
cout<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7-12 Dijkstra算法(模板) (30 分)
#include<bits/stdc++.h>
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define inf 0x3f3f3f3f
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
const int N = 2e5 + 10;
using namespace std;
int n,m,s,ed; // 点数、边数、起点、终点
int e[N],w[N],ne[N],h[N],idx; // 邻接表存储所有边
ll dist[N]; // 记录距离
bool st[N]; // 标记是否走过
void add(int u,int v,int k){ //加边
e[idx]=v,w[idx]=k,ne[idx]=h[u],h[u]=idx++;
}
void Dijkstra(){ // Dijkstra求最短路
mem(dist,0x3f); // 距离初始化
priority_queue<PII,vector<PII>,greater<PII> >q; // 定义优先队列
q.push({0,s}); // 把起点放入队列
dist[s]=0; // 起点距离变为0
while(q.size()){
auto t=q.top(); q.pop();
int dis=t.x,ver=t.y;
if(st[ver]) continue;
st[ver]=1;
for(int i=h[ver];~i;i=ne[i]){ // 松弛操作
int j=e[i];
if(dist[j]>dis+w[i]){
dist[j]=dis+w[i];
q.push({dist[j],j});
}
}
}
cout<<dist[ed]<<endl;
}
inline void solve(){
cin>>n>>m>>s>>ed;
int u,v,k;
mem(h,-1); // 节点清空
while(m--){ // 加边
cin>>u>>v>>k;
add(u,v,k);
add(v,u,k);
}
Dijkstra();
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}

题解&spm=1001.2101.3001.5002&articleId=120795343&d=1&t=3&u=bbbcfa4980d6482591c596738123ee24)
406

被折叠的 条评论
为什么被折叠?



