3.亲爱的题题们
3.0 模板floyd
B3647 【模板】Floyd - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
数据水,不用判>INF/2
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
//用7fffffff或者多输几个9就溢出成负数
int main(){
int n,e;
cin>>n>>e;
int E[101][101];
for(int i=0;i<101;i++){
for(int j=0;j<101;j++){
E[i][j]=INF;
E[i][i]=0;
}
}
for(int i=0;i<e;i++){
int u,v,w;
cin>>u>>v>>w;
E[u][v]=min(E[u][v],w);
E[v][u]=E[u][v];
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
E[i][j]=min(E[i][j],E[i][k]+E[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(j==1)cout<<E[i][j];
else{
cout<<" "<<E[i][j];
}
}
if(i!=n)cout<<endl;
}
}
3.1 模板最短路x1
P3371 【模板】单源最短路径(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
2147483647是个好数字,是32_int表示的最大值,前面留一个符号位,2^31-1=(1<<31)-1
移位运算符怎么用,看下面的程序
这也看出define是编译时把代码文本替换了
#include<iostream>
#define INF1 1<<31-1
#define INF2 (1<<31)-1
#define INF3 ((1<<31)-1)
using namespace std;
int main(){
cout<<INF1<< " "<<INF2<<" "<<INF3<<endl;
long long x1=INF1,x2=INF2,x3=INF3;
cout<<x1<<" "<<x2<< " " <<x3;
}
输出
130 2147483647 2147483647
1073741824 2147483647 2147483647
3.1 模板最短路x2
单源
边权正数,dijkstra
10^5内,朴素即可搞定
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int s,t,n,m;
long disic[1001];
long disii[1001][1001];
bool book[1001]={0};
void dijkstra(){
disic[s]=0;
book[s]=1;//if(!book[i])
for(int i=1;i<=n;i++)if(!book[i])disic[i]=min(disic[i],disic[s]+disii[i][s]);
for(int i=1;i<=n;i++){
long temp=INF;
int t0=-1;
for(int i=2;i<=n;i++){
if(!book[i]&&disic[i]<temp){
temp=disic[i];
t0=i;
}
}
if(t0==-1)continue;//最后10%
book[t0]=1;
for(int i=1;i<=n;i++)if(!book[i])disic[i]=min(disic[i],disic[t0]+disii[i][t0]);
}
if(disic[t]==INF)cout<<-1;
else cout<<disic[t];
}
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=n;i++){
disic[i]=INF;
disii[i][i]=0;
for(int j=1;j<i;j++){
disii[i][j]=INF;
disii[j][i]=INF;
}
}
for(int i=1;i<=m;i++){
int u,v;long w;
cin>>u>>v>>w;
disii[u][v]=min(disii[u][v],w);
disii[v][u]=disii[u][v];
}
dijkstra();
}
3.2 模板最短路x3
有坑
#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#define ll long long
#define INF 0x3f3f3f3f
ll total=0;
ll n,m,k,s,t;
ll dist[1000001];
bool st[1000001]={0};
ll head[1000001];
struct EDGE{
ll next;
ll to;
ll w;
}edge[10000001];
void addedge(ll u,ll v,ll w){
edge[++total].next=head[u];
edge[total].to=v;
edge[total].w=w;
head[u]=total;
}
void dijkstra(){
priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>>heap;
heap.push({0,s});
dist[s]=0;
while(!heap.empty()){
pair<ll,ll>temp=heap.top();
heap.pop();
ll x=temp.first,y=temp.second;
if(st[y])continue;
st[y]=true;
for(ll i=head[y];i!=-1;i=edge[i].next){
ll t0=edge[i].to;
if(dist[t0]>x+edge[i].w){
dist[t0]=x+edge[i].w;
heap.push({dist[t0],t0});
}
}
}
ll ans=INF;
for(ll i=0;i<=k;i++)ans=min(ans,dist[t+i*n]);
if(ans==INF)cout<<-1;
else cout<<ans;
}
int main()
{
cin>>n>>m>>k>>s>>t;
for(ll i=0;i<=(k+1)*n;i++){head[i]=-1;dist[i]=INF;}
for(ll i=1;i<=m;i++){
ll u,v,w;cin>>u>>v>>w;
addedge(u,v,w);
addedge(v,u,w);
for(int j=1;j<=k;j++){
addedge(u+j*n,v+j*n,w);
addedge(v+j*n,u+j*n,w);
addedge(u+(j-1)*n,v+j*n,0);
addedge(v+(j-1)*n,u+j*n,0);
}
}
dijkstra();
}
3.3 差分约束
边反着建
建立源点0,到其他点均有一条权为0的有向边
由于是bellman-ford是对边操作,不会dis[]全为0
跟新:
为了防止不连通(可能有那么一个难找的点可以做源点,也可能根本没有)加入源点0
0要到别的点都有边,(全是正数只是赠品)
从0开始spfa
P5960 【模板】差分约束 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int dist[5001];
struct EDGE{
int u;
int v;
int w;
}edge[10001];
void bellman(){
bool ok;
for(int i=1;i<=n+1;i++){
ok=1;
for(int j=1;j<=m+n;j++){
int u=edge[j].u;int v=edge[j].v;
//
if(dist[u]!=INF&&dist[v]>dist[u]+edge[j].w){
dist[v]=dist[u]+edge[j].w;
if(ok==true)ok=false;
}
}
if(ok==1)break;
}
if(ok!=1)cout<<"NO";
else {
for(int i=1;i<=n;i++){if(i!=1)cout<<" ";cout<<dist[i];}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
dist[i]=INF;
edge[i+m].u=0;
edge[i+m].v=i;
edge[i+m].w=0;
}
for(int i=1;i<=m;i++){
cin>>edge[i].v>>edge[i].u>>edge[i].w;
}
bellman();
}