《算法竞赛进阶指南》------图论篇

文章目录

    • 0x01 Telephone Lines POJ - 3662
    • 0x02 P1073 [NOIP2009 提高组] 最优贸易
    • 0x03 道路和航线 BZOJ2200
    • 0x04 Sorting It All Out POJ - 1094 topo
    • 0x05 Sightseeing trip POJ - 1734 最小环问题
    • 0x06 Cow Relays POJ - 3613 S到E经过k条边的最短路
    • 0x07 走廊泼水节 (Kruskal)

0x01 Telephone Lines POJ - 3662

Telephone Lines
题意:从1到N修一条电缆,有p对电线杆之间是可以连接的,电信公司可以提供k条电缆,其他的由John提供,求john提供的电缆的最长的那根的长度(ret)。
思路:实则是求最短最长的边。
二分结果(sum)。对于 边值>sum, 电信公司需要提供电缆。
用djk 计算 1->n 路径上的最短路径。 满足d[n]< k ,sum是一个符合的结果。
代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=2e4+10;
const ll P=1e9+7;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll n,p,k;
ll head[N],ver[N],nex[N],edgevalue[N];
ll cnt;
void addedge(ll u,ll v,ll value)
{ver[++cnt]=v;edgevalue[cnt]=value;nex[cnt]=head[u];head[u]=cnt;
}
priority_queue<pair<int,int>> q;
ll d[N],v[N];
bool ischeck(ll sum)
{memset(d,0x3f,sizeof(d));memset(v,0,sizeof(v));while(!q.empty()){q.pop();}d[1]=0;q.push(make_pair(0,1));  //  距离  点while(!q.empty()){ll x=q.top().second;q.pop();if(v[x]) continue;v[x]=1;for(int i=head[x];i;i=nex[i]){int y=ver[i],z=edgevalue[i];if(z> sum)  z=1;else z=0;if(d[y]>d[x]+z){d[y]=d[x]+z;q.push(make_pair(-d[y],y));}}if(v[n]==1) break;}// printf("%lld\n",d[n]);// getchar();if(d[n]<=k) return true;elsereturn false;
}
void solve(){n=read();p=read();k=read();ll u,v,value;rep(i,1,p){u=read();v=read();value=read();addedge(u,v,value);addedge(v,u,value);        }ll l=0,r=1000010;ll mid;while(l<r){mid=(l+r)>>1;// printf("l:%lld r:%lld mid:%lld\n",l,r,mid);if(ischeck(mid)){r=mid;}else{l=mid+1;}}if(r==1000010) printf("-1\n");elseprintf("%lld\n",r);return ;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x02 P1073 [NOIP2009 提高组] 最优贸易

最优贸易
题意:从1到达n号,在沿途中可选一点购买水晶球,在此之后可卖出去水晶球。商人阿龙只能购买一次,
问商人阿龙 旅游结束后,通过这样的方式最多赚取多少旅费?途中 一座城市可被重复经过。
数据范围: 1 < = n < = 1 0 5 , 1 < = m < = 5 ∗ 1 0 5 1<=n<=10^5,1<=m<=5*10^5 1<=n<=105,1<=m<=5105
思路:
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=1e6+10;
const ll P=1e9+7;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll n,m;
ll vVAlue[N];
ll head[N],nex[N],ver[N];
ll cnt;
ll addedge(ll u,ll v)
{ver[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;   
}ll vis[N];
void djk(ll u,ll *D,ll flag)
{     priority_queue< pair<int,int> > q;memset(vis,0,sizeof(vis));if(flag==1)rep(i,1,n) D[i]=200;elserep(i,1,n) D[i]=0;//    rep(i,1,n)  cout<<D[i]<<" "; cout<<endl;D[u]=vVAlue[u];q.push(make_pair(D[u],u));while(!q.empty()){ll x=q.top().second;q.pop();for(int i=head[x];i;i=nex[i]){   //   cout<<"321"<<endl;ll y=ver[i];if(flag==1){if(D[y] > D[x]){   // cout<<vVAlue[y]<<" "<<D[x]<<endl;D[y]=min(vVAlue[y],D[x]);q.push(make_pair(-D[y],y));}}else {if(D[y] < D[x]){   //cout<<vVAlue[y]<<" "<<D[x]<<endl;D[y]=max(vVAlue[y],D[x]);q.push(make_pair(D[y],y));}}  }}//   cout<<flag<<endl;//   rep(i,1,n)//   {//       printf("u:%lld  value:%lld\n",i,D[i]);//   }return ;
}
struct zw
{ll x,y,z;
}a[N];
ll D[N],F[N];
void solve(){n=read();m=read();rep(i,1,n) vVAlue[i]=read();ll x,y,z;rep(i,1,m){a[i].x=read();a[i].y=read();a[i].z=read();addedge(a[i].x,a[i].y);if(a[i].z==2){addedge(a[i].y,a[i].x);}}djk(1,D,1);cnt=0;memset(head,0,sizeof(head));rep(i,1,m){addedge(a[i].y,a[i].x);if(a[i].z==2){addedge(a[i].x,a[i].y);}}djk(n,F,-1);ll sum=0;rep(i,1,n) sum=max(sum,F[i]-D[i]);printf("%lld\n",sum);return ;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x03 道路和航线 BZOJ2200

拓扑排序,djk,
道路和航线
题意:
在这里插入图片描述思路:
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=2e5+10;
// const ll P=1e9+7;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll n,R,P,S;
ll  cnt;
ll head[N],nex[N],edgevalue[N],var[N];
ll D[N],vis[N];
ll num[N],in[N];
ll ans;   // 编号个数
queue<int> c;  //存放编号
priority_queue< pair<ll,int>> q;
void addedge(ll u,ll v,ll value)
{var[++cnt]=v;edgevalue[cnt]=value;nex[cnt]=head[u];head[u]=cnt;
}
void dfs(ll u)
{   num[u]=ans;for(int i=head[u];i;i=nex[i]){int v=var[i];if(num[v]) continue;dfs(v);}return ;
}
void  djk(ll s)
{     ll u,v,value;memset(D,0x7f,sizeof(D));memset(vis,0,sizeof(vis));D[s]=0;c.push(num[s]);rep(i,1,ans){if(in[i]==0 and num[s]!=i)c.push(i);}while(!c.empty()){ll x=c.front();c.pop();rep(i,1,n){if(num[i]==x) q.push(make_pair(-D[i],i));}while(!q.empty()){u=q.top().second;q.pop();if(vis[u])  continue;vis[u]=1;for(int i=head[u];i;i=nex[i]){v=var[i];value=edgevalue[i];if(D[v] > D[u]+value){D[v]=D[u]+value;if(num[u]==num[v]){q.push(make_pair(-D[v],v));}}if(num[u]!=num[v]){   in[num[v]]--;if(in[num[v]]==0){c.push(num[v]);}} }}}
}
void solve(){n=read();R=read();P=read();S=read();ll u,v,value;rep(i,1,R){u=read(); v=read(); value=read();addedge(u,v,value);addedge(v,u,value);}rep(i,1,n){if(num[i]==0){ans++;dfs(i);}}rep(i,1,P){u=read();v=read();value=read();in[num[v]]++;addedge(u,v,value);}djk(S);rep(i,1,n){if(D[i]>0x3f3f3f3f) printf("NO PATH\n");else printf("%lld\n",D[i]);}return ;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x04 Sorting It All Out POJ - 1094 topo

Sorting It All Out
题意:
在这里插入图片描述
思路:
在这里插入图片描述
代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=30;
const ll P=1e9+7;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll n,m,cnt;
ll in[N],in1[N];
ll head[N],var[1000],nex[1000];
void addedge(ll u,ll v)
{var[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;
}
ll ans=0;
char ch[N];
ll topo()
{rep(i,0,n-1) in[i]=in1[i];ans=0;queue<int> q;rep(i,0,n-1){if(in[i]==0)  q.push(i);}bool logo=true;ll u,v;while(!q.empty()){if(q.size()>1) logo=false;ll u=q.front();ch[ans++]=u;q.pop();for(int i=head[u];i;i=nex[i]){v=var[i];if((--in[v])==0) q.push(v);} }// cout<<ans<<" "<<logo<<n<<endl;if(ans<n) return -1;else {if(logo==true) return 1;else return 0;}
}
void solve(){while(1){n=read();m=read();if(n==0 and m==0) break;rep(i,0,n){in1[i]=0;head[i]=0;cnt=0;}char x,y;ll u,v;ll res=0;ll inde=0;rep(i,1,m){cin>>x>>y>>y;u=x-'A';v=y-'A';addedge(u,v);in1[v]++;if(res==0){res=topo();// cout<<res<<endl;inde=i;} }// cout<<res<<endl;if(res==0) cout<<"Sorted sequence cannot be determined."<<endl;else if(res==-1) cout<<"Inconsistency found after "<<inde<<" relations."<<endl;else if(res==1) {cout<<"Sorted sequence determined after "<<inde<<" relations: ";rep(i,0,ans-1)  printf("%c",ch[i]+'A');cout<<"."<<endl;}}
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x05 Sightseeing trip POJ - 1734 最小环问题

留下一个小疑问点: int 和 ll a=0x3f3f3f3f 在这道题中 使用ll a=0x3f3f3f3f 会错。
Sightseeing trip
题意:
在这里插入图片描述
思路:弗洛伊德, 回溯路径。
外层循环k开始,对所以的路径刷新,添上k和步添上k
这个算法的思想很关键
在这里插入图片描述

在这里插入图片描述

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=300+10;
using namespace std;
int a[N][N],dist[N][N],pos[N][N];
ll n,m;
ll ans=1e8;
vector<int> path;
void get_path(int x,int y){if(pos[x][y]==0) return ;get_path(x,pos[x][y]);path.push_back(pos[x][y]);get_path(pos[x][y],y);
}
void solve(){cin>>n>>m;//  memset(a,0x3f,sizeof(a));for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){a[i][j]=1e8;}}for(int i=0;i<=n;i++) a[i][i]=0;for(int i=1;i<=m;i++){   int u,v,w;cin>>u>>v>>w;a[u][v]=a[v][u]=min(a[u][v],w);}memcpy(dist,a,sizeof(a));for(int k=1;k<=n;k++){for(int i=1;i<k;i++){for(int j=i+1;j<k;j++){if(dist[i][j]+a[j][k]+a[k][i]<ans){ans=dist[i][j]+a[j][k]+a[k][i];path.clear();path.push_back(i);get_path(i,j);path.push_back(j);path.push_back(k);}}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(dist[i][j]> dist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];pos[i][j]=k;}}}}if(ans == 1e8){cout << "No solution." << endl;}else {for(int i=0;i<(int)path.size();i++){cout<<path[i]<<" ";}}return ;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x06 Cow Relays POJ - 3613 S到E经过k条边的最短路

传送门
题意:
在这里插入图片描述
思路: 点编号映射,矩阵快速幂
代码如下:

#include<iostream>
#include<cstring>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=2e5+10;
const ll P=1e9+7;
const ll INF=0x3f3f3f3f;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll  p[1010];
ll  a[300];
ll cnt;
struct M{ll edge[210][210];void init(){rep(i,1,200){rep(j,1,200){edge[i][j]=INF;                }}}
};
M add(M a,M b){M sum;sum.init();rep(i,1,cnt){rep(j,1,cnt){rep(k,1,cnt){sum.edge[i][j]=min(sum.edge[i][j],a.edge[i][k]+b.edge[k][j]);}}}return sum;
}
void solve(){ll n,t,s,e;cin>>n>>t>>s>>e;ll w,u,v;M sum;sum.init();for(int i=1;i<=t;i++){cin>>w>>u>>v;if(!p[u]){p[u]=(++cnt);a[cnt]=u;}if(!p[v]){p[v]=(++cnt);a[cnt]=v;}sum.edge[p[u]][p[v]]=min(w, sum.edge[p[u]][p[v]]);sum.edge[p[v]][p[u]]=min(w, sum.edge[p[v]][p[u]]);}M ans;memcpy(ans.edge,sum.edge,sizeof(sum.edge));// sum=add(sum,sum);n--;while(n){if(n&1) ans=add(ans,sum);sum=add(sum,sum);n>>=1;}cout<<ans.edge[p[s]][p[e]]<<endl;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);solve();getchar();getchar();return 0;
}

0x07 走廊泼水节 (Kruskal)

走廊泼水节
题意:
在这里插入图片描述
思路: 克里斯特+模拟
在这里插入图片描述

#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=1e4+10;
const ll P=1e9+7;
ll read(){ll s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
using namespace std;
ll fa[N];
ll num[N];
ll  getfa(ll x){return x==fa[x] ? x: fa[x]=getfa(fa[x]);
}
struct zw{int x,y,z;
}a[N];
bool operator <(zw a,zw b){return a.z<b.z;
}
void solve(){ll n;cin>>n;rep(i,1,n-1){cin>>a[i].x>>a[i].y>>a[i].z;}rep(i,1,n){fa[i]=i;num[i]=1;}sort(a+1,a+n);ll sum=0;for(int i=1;i<=n-1;i++){int x=getfa(a[i].x);int y=getfa(a[i].y);if(x==y) continue;sum+=( num[x]*num[y]-1 )*(a[i].z+1);fa[y]=x;num[x]+=num[y];}cout<<sum<<endl;return ;
}
int main (){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T=read();while(T--)solve();getchar();getchar();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/259780.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rxjava2的CompositeDisposable

最近&#xff0c;项目中遇到了一个历史遗留问题&#xff1a;未登录状态请求需要登录的接口&#xff0c;接口返回201之后&#xff0c;再次登录&#xff0c;刷新无法请求接口的问题。 于是&#xff0c;经过一些类深入排查。发现&#xff1a;在项目基建的网络请求框架中&#xff0…

Windows 12 和 AI 计算机

据商业时报消息 &#xff0c;微软计划于 2024 年 6 月发布Windows 12。 新版本的操作系统将伴随集成人工智能。 该数据基于广达首席执行官林百里和宏基陈杰森在中国台北医疗科技展上的发言。 虽然这篇文章没有直接引用微软高管的话&#xff0c;但它是根据他们的评论得出的结…

【Fastadmin】一个完整的轮播图功能示例

目录 1.效果展示&#xff1a; 列表 添加及标记页面同 2.建表&#xff1a; 3.时候crud一键生成并创建控制器 4.html页面 add.html edit.html index.php 5.js页面 6.小知识点 1.效果展示&#xff1a; 列表 添加及标记页面同 2.建表&#xff1a; 表名&#xff1a;fa_x…

【qt】Qt+OpenCv读取带有中文路径的图片

【opencv4.5.1版本】下载exe解压即可。。。https://opencv.org/releases/page/2/ 【qt5.15.2】 pro文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. # In order to …

控制系统设计中的凸优化

凸优化&#xff0c;或叫做凸最优化&#xff0c;凸最小化&#xff0c;是数学最优化的一个子领域&#xff0c;研究定义于凸集中的凸函数最小化的问题。 在控制系统中&#xff0c;凸优化是一种有效的设计方法&#xff0c;用于解决具有凸集约束的优化问题。凸优化问题通常涉及最小…

最简单的基于 FFmpeg 的音频解码器

最简单的基于 FFmpeg 的音频解码器 最简单的基于 FFmpeg 的音频解码器正文参考 参考雷霄骅博士的文章&#xff0c;链接&#xff1a;最简单的基于FFMPEGSDL的音频播放器&#xff1a;拆分-解码器和播放器 最简单的基于 FFmpeg 的音频解码器 正文 FFmpeg 音频解码器实现了音频数…

硕士毕业论文格式修改要点_word

目录 0、最开始要做的事情1、更改样式&#xff08;先善器&#xff09;2、多级标题&#xff08;解决自动更新问题必要的基础设置&#xff09;2、插入图片&#xff08;1&#xff09;设置一个图片样式——“无间隔”&#xff08;2&#xff09;插入题注&#xff08;3&#xff09;修…

JavaScript常用技巧专题一

文章目录 一、前言二、生成随机颜色的两种方式2.1、生成RandomHexColor2.2、生成随机RGBA 三、复制内容到剪贴板的两种方式3.1、方式13.2、方式2 四、获取URL中的查询参数五、打乱数组六、深拷贝一个对象七、确保元素在可见区域内八、获取当前选中的文本九、浏览器cookie9.1、获…

低多边形3D建模石头材质纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

单例模式---饿汉式、懒汉式

一、什么是单例模式 单例模式&#xff0c;指的是一个类中的对象只能有一个&#xff0c;它在内存中只会创建一次对象的设计模式。 二、饿汉式 public class SingleTon {// 私有的构造方法private SingleTon() {};// 1. 饿汉式private static SingleTon instance new SingleTon…

Flink 使用场景

Apache Flink 功能强大&#xff0c;支持开发和运行多种不同种类的应用程序。它的主要特性包括&#xff1a;批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。Flink 不仅可以运行在包括 YARN、 Mesos、K8s 在内的多种资源管理框架上&#xff0c;还支持…

HarmonyOS鸿蒙操作系统架构开发

什么是HarmonyOS鸿蒙操作系统&#xff1f; HarmonyOS是华为公司开发的一种全场景分布式操作系统。它可以在各种智能设备&#xff08;如手机、电视、汽车、智能穿戴设备等&#xff09;上运行&#xff0c;具有高效、安全、低延迟等优势。 目录 HarmonyOS 一、HarmonyOS 与其他操…