来自:算法提高课
第三章 图论
3.1 单源最短路的建图方式
3.1.1 1129. 热浪
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2510,M=6210,INF=1e9;
int n,m,s,ed;
int h[N],e[2*M],w[2*M],ne[2*M],idx;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int spfa(int s)
{
fill(dis,dis+N,INF);
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+w[i])
{
dis[j]=dis[t]+w[i];
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
return dis[ed];
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m>>s>>ed;
fill(h,h+N,-1);
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
cout<<spfa(s);
return 0;
}
3.1.2 1128. 信使
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110,M=410,INF=1e9;
int n,m;
int h[N],e[M],w[M],ne[M],idx;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void spfa(int s)
{
fill(dis,dis+N,INF);
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+w[i])
{
dis[j]=dis[t]+w[i];
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
}
int main()
{
fill(h,h+N,-1);
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
spfa(1);
int _max=-INF;
for(int i=1;i<=n;i++)
{
if(dis[i]==INF)
{
cout<<-1<<endl;
return 0;
}
if(_max<dis[i])
{
_max=dis[i];
}
}
cout<<_max<<endl;
return 0;
}
3.1.3 1127. 香甜的黄油
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=810,M=2910,INF=1e9;
int n,p,C;
int h[N],e[M],w[M],ne[M],idx;
int dis[N];
bool st[N];
int cows[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void spfa(int s)
{
fill(dis,dis+N,INF);
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+w[i])
{
dis[j]=dis[t]+w[i];
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
}
int main()
{
fill(h,h+N,-1);
cin>>n>>p>>C;
for(int i=0;i<n;i++)
{
cin>>cows[i];
}
for(int i=0;i<C;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
int ans=INF;
for(int i=1;i<=p;i++)
{
spfa(i);
int sum=0;
for(int j=0;j<n;j++)
{
if(dis[cows[j]]==INF)
{
sum=INF;
break;
}
else
{
sum+=dis[cows[j]];
}
}
ans=min(ans,sum);
}
cout<<ans<<endl;
return 0;
}
3.1.4 1126. 最小花费
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=2010,M=200010,INF=1e9;
int n,m,A,B;
int h[N],e[M],ne[M],idx;
double w[M];
bool st[N];
double dis[N];
void add(int a,int b,double c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
double spfa(int s)
{
dis[s]=1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]<dis[t]*w[i])
{
dis[j]=dis[t]*w[i];
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
return dis[B];
}
int main()
{
fill(h,h+N,-1);
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b;
double c;
cin>>a>>b>>c;
c=(100-c)/100;
add(a,b,c),add(b,a,c);
}
cin>>A>>B;
printf("%.8f",100/spfa(A));
return 0;
}
3.1.5 920. 最优乘车
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=510,INF=1e9;
int m,n;
int g[N][N];
int dis[N];
int stop[N];
void bfs()
{
fill(dis,dis+N,INF);
queue<int> q;
dis[1]=0;
q.push(1);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(g[t][i]&&dis[i]>dis[t]+1)
{
dis[i]=dis[t]+1;
q.push(i);
}
}
}
}
int main()
{
cin>>m>>n;
getchar();
string line;
while(m--)
{
getline(cin,line);
int cnt=0,p;
stringstream ssin(line);
while(ssin>>p) stop[cnt++]=p;
for(int i=0;i<cnt;i++)
{
for(int j=i+1;j<cnt;j++)
{
g[stop[i]][stop[j]]=1;
}
}
}
bfs();
if(dis[n]==INF) cout<<"NO";
else cout<<dis[n]-1;
return 0;
}
3.1.6 903. 昂贵的聘礼
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=110,INF=1e9;
int m,n;
int g[N][N];
int d[N];
int w[N],L[N];
bool st[N];
vector<PII> node[N];
int spfa(int left,int right)
{
fill(d,d+N,INF);
d[0]=0;
queue<int> q;
for(int i=0;i<=n;i++)
{
q.push(i);
st[i]=true;
}
while(!q.empty())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=0;i<=n;i++)
{
if(g[t][i]!=INF)
{
if(L[i]>=left&&L[i]<=right&&d[i]>d[t]+g[t][i])
{
d[i]=d[t]+g[t][i];
if(!st[i])
{
q.push(i);
st[i]=true;
}
}
}
}
}
return d[1];
}
int main()
{
fill(g[0],g[0]+N*N,INF);
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int p,l,x;
cin>>p>>l>>x;
w[i]=p;
L[i]=l;
for(int j=0;j<x;j++)
{
int t,v;
cin>>t>>v;
node[i].push_back(make_pair(t,v));
}
}
for(int i=1;i<=n;i++)
{
g[i][i]=0;
for(int j=0;j<node[i].size();j++)
{
int t=node[i][j].first,v=node[i][j].second;
if(abs(L[i]-L[t])<=m)
{
g[t][i]=min(g[t][i],v);
}
}
}
for(int i=1;i<=n;i++) g[0][i]=w[i];
int ans=INF;
for(int i=L[1]-m;i<=L[1];i++)
{
ans=min(ans,spfa(i,i+m));
}
cout<<ans;
return 0;
}
3.2 单源最短路的综合应用
3.2.1 1135. 新年好
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=50010,M=200010,INF=1e9;
int n,m;
int h[N],e[M],w[M],ne[M],idx;
bool st[N];
int dis[6][N];
int source[6];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void djk(int s,int dis[])
{
fill(dis,dis+N,INF);
fill(st,st+N,false);
dis[s]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push(make_pair(0,s));
while(heap.size())
{
PII t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[ver]+w[i])
{
dis[j]=dis[ver]+w[i];
heap.push(make_pair(dis[j],j));
}
}
}
}
int dfs(int u,int start,int distance)
{
if(u>5) return distance;
int res=INF;
for(int i=1;i<=5;i++)
{
if(!st[i])
{
int next=source[i];
st[i]=true;
res=min(res,dfs(u+1,i,distance+dis[start][next]));
st[i]=false;
}
}
return res;
}
int main()
{
fill(h,h+N,-1);
cin>>n>>m;
for(int i=1;i<=5;i++) cin>>source[i];
source[0]=1;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
fill(st,st+N,false);
for(int i=0;i<6;i++) djk(source[i],dis[i]);
cout<<dfs(1,0,0);
return 0;
}
3.2.2 340. 通信线路
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=20010,INF=1e9;
int n,m,K;
int h[N],e[M],w[M],ne[M],idx;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool check(int bound)
{
fill(dis,dis+N,INF);
fill(st,st+N,false);
dis[1]=0;
deque<int> q;
q.push_back(1);
while(!q.empty())
{
int t=q.front();
q.pop_front();
if(st[t])
continue;
st[t]=true;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i],v=w[i]>bound;
if(dis[j]>dis[t]+v)
{
dis[j]=dis[t]+v;
if(!v)
{
q.push_front(j);
}
else
{
q.push_back(j);
}
}
}
}
return dis[n]<=K;
}
int main()
{
fill(h,h+N,-1);
cin>>n>>m>>K;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
int l=0,r=1e6+1;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(r==1e6+1) r=-1;
cout<<r<<endl;
return 0;
}
3.2.3 342. 道路与航线
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=25010,M=1500010,INF=1e9;
int h[N],e[M],w[M],ne[M],idx;
int n,r,p,s;
int dis[N];
bool st[N];
int id[N];
vector<int> block[N]; //连通块编号
int bcnt; //连通块个数
queue<int> q; //拓扑排序队列
int din[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int bid)
{
id[u]=bid;
block[bid].push_back(u);
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!id[j]) dfs(j,bid);
}
}
void djk(int bid)
{
priority_queue<PII,vector<PII>,greater<PII> > heap;
for(int i=0;i<block[bid].size();i++)
{
int ver=block[bid][i];
heap.push(make_pair(dis[ver],ver));
}
while(heap.size())
{
PII t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[ver]+w[i])
{
dis[j]=dis[ver]+w[i];
if(id[j]==id[ver]) heap.push(make_pair(dis[j],j));
}
if(id[j]!=id[ver]&&--din[id[j]]==0) q.push(id[j]);
}
}
}
void topsort()
{
fill(dis,dis+N,INF);
dis[s]=0;
for(int i=1;i<=bcnt;i++)
{
if(!din[i])
{
q.push(i);
}
}
while(q.size())
{
int t=q.front();
q.pop();
djk(t);
}
}
int main()
{
ios::sync_with_stdio(0);
fill(h,h+N,-1);
cin>>n>>r>>p>>s;
for(int i=0;i<r;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
for(int i=1;i<=n;i++)
{
if(!id[i])
{
bcnt++;
dfs(i,bcnt);
}
}
for(int i=0;i<p;i++)
{
int a,b,c;
cin>>a>>b>>c;
din[id[b]]++;
add(a,b,c);
}
topsort();
for(int i=1;i<=n;i++)
{
if(dis[i]>=INF/2) cout<<"NO PATH"<<endl;
else cout<<dis[i]<<endl;
}
return 0;
}
3.2.4 341. 最优贸易
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,M=2000010,INF=1e9;
int n,m;
int w[N];
int hs[N],ht[N],e[M],ne[M],idx;
int dmin[N],dmax[N];
int q[N];
bool st[N];
void add(int h[],int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void spfa(int h[],int dis[],int type)
{
queue<int> q;
if(type==0)
{
fill(dis,dis+N,INF);
dis[1]=w[1];
q.push(1);
}
else
{
fill(dis,dis+N,-INF);
dis[n]=w[n];
q.push(n);
}
while(q.size())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(type==0&&dis[j]>min(dis[t],w[j])||type==1&&dis[j]<max(dis[t],w[j]))
{
if(type==0)
{
dis[j]=min(dis[t],w[j]);
}
else
{
dis[j]=max(dis[t],w[j]);
}
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
}
int main()
{
cin>>n>>m;
fill(hs,hs+N,-1);
fill(ht,ht+N,-1);
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(hs,a,b),add(ht,b,a);
if(c==2) add(hs,b,a),add(ht,a,b);
}
spfa(hs,dmin,0);
spfa(ht,dmax,1);
int res=0;
for(int i=1;i<=n;i++)
{
res=max(res,dmax[i]-dmin[i]);
}
cout<<res;
return 0;
}
3.3 单源最短路的扩展应用
3.3.1 1137. 选择最佳线路
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1010,M=40010,INF=1e9;
int n,m;
int ed;
int h[N],w[M],e[M],ne[M],idx;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int djk(int s)
{
fill(dis,dis+N,INF);
fill(st,st+N,false);
dis[s]=0;
priority_queue<PII,vector<PII>,greater<PII> > heap;
heap.push(make_pair(0,s));
while(heap.size())
{
PII t=heap.top();
heap.pop();
int ver=t.second;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[ver]+w[i])
{
dis[j]=dis[ver]+w[i];
heap.push(make_pair(dis[j],j));
}
}
}
return dis[ed];
}
int main()
{
while(cin>>n>>m>>ed)
{
fill(h,h+N,-1);
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(b,a,c);
}
djk(ed);
int num,start;
cin>>num;
int ans=INF;
for(int i=0;i<num;i++)
{
cin>>start;
ans=min(ans,dis[start]);
}
if(ans!=INF) cout<<ans<<endl;
else cout<<-1<<endl;
}
return 0;
}
3.3.2 1131. 拯救大兵瑞恩
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=11,M=400,P=1<<10,INF=1e9;
int n,m,p,k;
int h[N*N],e[M],w[M],ne[M],idx;
int g[N][N],key[N*N];
int dis[N*N][P];
bool st[N*N][P];
set<PII> edges;
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void build()
{
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int u=0;u<4;u++)
{
int x=i+dx[u],y=j+dy[u];
if(!x||x>n||!y||y>m) continue;
int a=g[i][j],b=g[x][y];
if(!edges.count(make_pair(a,b))) add(a,b,0);
}
}
}
}
int bfs()
{
//memset(dis,0x3f,sizeof dis);
fill(dis[0],dis[0]+N*N*P,INF);
dis[1][0]=0;
deque<PII> q;
q.push_back(make_pair(1,0));
while(q.size())
{
PII t=q.front();
q.pop_front();
if(st[t.first][t.second]) continue;
st[t.first][t.second]=true;
if(t.first==n*m) return dis[t.first][t.second];
if(key[t.first])
{
int state=t.second|key[t.first];
if(dis[t.first][state]>dis[t.first][t.second])
{
dis[t.first][state]=dis[t.first][t.second];
q.push_front(make_pair(t.first,state));
}
}
for(int i=h[t.first];i!=-1;i=ne[i])
{
int j=e[i];
if(w[i]&&!(t.second>>w[i]-1&1)) continue;
if(dis[j][t.second]>dis[t.first][t.second]+1)
{
dis[j][t.second]=dis[t.first][t.second]+1;
q.push_back(make_pair(j,t.second));
}
}
}
return -1;
}
int main()
{
cin>>n>>m>>p>>k;
for(int i=1,t=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
g[i][j]=t++;
}
}
fill(h,h+N*N,-1);
for(int i=0;i<k;i++)
{
int x1,y1,x2,y2,c;
cin>>x1>>y1>>x2>>y2>>c;
int a=g[x1][y1],b=g[x2][y2];
edges.insert(make_pair(a,b)),edges.insert(make_pair(b,a));
if(c) add(a,b,c),add(b,a,c);
}
build();
int num;
cin>>num;
for(int i=0;i<num;i++)
{
int x,y,id;
cin>>x>>y>>id;
key[g[x][y]]|=1<<id-1;
}
cout<<bfs()<<endl;
return 0;
}
3.3.3 1134. 最短路计数
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,M=400010,mod=100003;
int n,m;
int h[N],e[M],ne[M],idx;
int dis[N],cnt[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs()
{
memset(dis,0x3f,sizeof dis);
dis[1]=0,cnt[1]=1;
queue<int> q;
q.push(1);
while(q.size())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+1)
{
dis[j]=dis[t]+1;
cnt[j]=cnt[t];
q.push(j);
}
else if(dis[j]==dis[t]+1)
{
cnt[j]=(cnt[j]+cnt[t])%mod;
}
}
}
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
bfs();
for(int i=1;i<=n;i++)
{
cout<<cnt[i]<<endl;
}
return 0;
}
3.3.4 383. 观光
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=10010;
struct Ver{
int ver,type,dist;
bool operator > (const Ver &w) const
{
return dist>w.dist;
}
Ver(int _ver,int _type,int _dist)
{
ver=_ver,type=_type,dist=_dist;
}
};
int n,m;
int S,T;
int h[N],e[M],w[M],ne[M],idx;
int dis[N][2],cnt[N][2];
bool st[N][2];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int djk()
{
memset(st,0,sizeof st);
memset(cnt,0,sizeof cnt);
memset(dis,0x3f,sizeof dis);
dis[S][0]=0,cnt[S][0]=1;
priority_queue<Ver,vector<Ver>,greater<Ver> > heap;
heap.push(Ver(S,0,0));
while(heap.size())
{
Ver t=heap.top();
heap.pop();
int ver=t.ver,type=t.type,distance=t.dist,_count=cnt[ver][type];
if(st[ver][type]) continue;
st[ver][type]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j][0]>distance+w[i])
{
dis[j][1]=dis[j][0],cnt[j][1]=cnt[j][0];
heap.push(Ver(j,1,dis[j][1]));
dis[j][0]=distance+w[i],cnt[j][0]=_count;
heap.push(Ver(j,0,dis[j][0]));
}
else if(dis[j][0]==distance+w[i])
{
cnt[j][0]+=_count;
}
else if(dis[j][1]>distance+w[i])
{
dis[j][1]=distance+w[i],cnt[j][1]=_count;
heap.push(Ver(j,1,dis[j][1]));
}
else if(dis[j][1]==distance+w[i])
{
cnt[j][1]+=_count;
}
}
}
int res=cnt[T][0];
if(dis[T][0]+1==dis[T][1]) res+=cnt[T][1];
return res;
}
int main()
{
int cases;
cin>>cases;
while(cases--)
{
cin>>n>>m;
memset(h,-1,sizeof h);
idx=0;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cin>>S>>T;
cout<<djk()<<endl;
}
return 0;
}
3.4 Floyd算法
3.4.1 1125. 牛的旅行
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=160;
const double INF=1e20;
char g[N][N];
PII q[N];
int n;
double d[N][N],maxd[N];
double get_dist(PII a,PII b)
{
double x=a.first-b.first,y=a.second-b.second;
return sqrt(x*x+y*y);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>q[i].first>>q[i].second;
}
for(int i=0;i<n;i++)
{
cin>>g[i];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i!=j)
{
if(g[i][j]=='1') d[i][j]=get_dist(q[i],q[j]);
else d[i][j]=INF;
}
}
}
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(d[i][j]<INF)
{
maxd[i]=max(maxd[i],d[i][j]);
}
}
}
double res1=0;
for(int i=0;i<n;i++)
res1=max(res1,maxd[i]);
double res2=INF;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(d[i][j]>=INF)
{
double dist=get_dist(q[i],q[j]);
res2=min(res2,maxd[i]+dist+maxd[j]);
}
}
}
printf("%.6f",max(res1,res2));
return 0;
}
3.4.2 343. 排序
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=30;
int n,m;
bool g[N][N],d[N][N];
bool st[N];
void floyd()
{
memcpy(d,g,sizeof d);
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
d[i][j]|=d[i][k]&&d[k][j];
}
}
}
}
int check()
{
for(int i=0;i<n;i++)
{
if(d[i][i])
return 2;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(!d[i][j]&&!d[j][i])
{
return 0;
}
}
}
return 1;
}
char get_min()
{
for(int i=0;i<n;i++)
{
if(!st[i])
{
bool flag=true;
for(int j=0;j<n;j++)
{
if(!st[j]&&d[j][i])
{
flag=false;
break;
}
}
if(flag)
{
st[i]=true;
return i+'A';
}
}
}
}
int main()
{
while(true)
{
cin>>n>>m;
if(n==0&&m==0)
break;
memset(g,0,sizeof g);
//注意type的意义和讲的时候不一样
int type=0,t;
for(int i=1;i<=m;i++)
{
string str;
cin>>str;
int a=str[0]-'A',b=str[2]-'A';
if(!type)
{
g[a][b]=1;
floyd();
type=check();
if(type) t=i;
}
}
if(!type)
cout<<"Sorted sequence cannot be determined."<<endl;
else if(type==2)
cout<<"Inconsistency found after "<<t<<" relations."<<endl;
else
{
memset(st,0,sizeof st);
cout<<"Sorted sequence determined after "<<t<<" relations: ";
for(int i=0;i<n;i++)
cout<<get_min();
cout<<"."<<endl;
}
}
return 0;
}
3.4.3 344. 观光之旅
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n,m;
int d[N][N],g[N][N];
int pos[N][N];
int path[N],cnt;
void get_path(int i,int j)
{
if(pos[i][j]==0) return;
int k=pos[i][j];
get_path(i,k);
path[cnt++]=k;
get_path(k,j);
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
for(int i=1;i<=n;i++) g[i][i]=0;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);
}
int res=INF;
memcpy(d,g,sizeof d);
for(int k=1;k<=n;k++)
{
for(int i=1;i<k;i++)
{
//for(int j=1;j<i;j++)
for(int j=i+1;j<k;j++)
{
if((long long)d[i][j]+g[i][k]+g[k][j]<res)
{
res=d[i][j]+g[i][k]+g[k][j];
cnt=0;
path[cnt++]=k;
path[cnt++]=i;
get_path(i,j);
path[cnt++]=j;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(d[i][j]>d[i][k]+d[k][j])
{
d[i][j]=d[i][k]+d[k][j];
pos[i][j]=k;
}
}
}
}
if(res==INF) cout<<"No solution.";
for(int i=0;i<cnt;i++)
{
cout<<path[i]<<" ";
}
return 0;
}
3.4.4 345. 牛站
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=210,M=2010,INF=0x3f3f3f3f;
int k,n,m,S,E;
int g[N][N];
int res[N][N];
void mul(int c[][N],int a[][N],int b[][N])
{
static int temp[N][N];
memset(temp,0x3f,sizeof temp);
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
temp[i][j]=min(temp[i][j],a[i][k]+b[k][j]);
}
}
}
memcpy(c,temp,sizeof temp);
}
void qmi()
{
memset(res,0x3f,sizeof res);
for(int i=1;i<=n;i++) res[i][i]=0;
while(k)
{
if(k&1) mul(res,res,g);
mul(g,g,g);
k>>=1;
}
}
int main()
{
cin>>k>>m>>S>>E;
memset(g,0x3f,sizeof g);
map<int,int> mp;
if(mp.count(S)==0) mp[S]=++n;
if(mp.count(E)==0) mp[E]=++n;
S=mp[S],E=mp[E];
while(m--)
{
int a,b,c;
cin>>c>>a>>b;
if(mp.count(a)==0) mp[a]=++n;
if(mp.count(b)==0) mp[b]=++n;
a=mp[a],b=mp[b];
g[a][b]=g[b][a]=min(g[a][b],c);
}
qmi();
cout<<res[S][E]<<endl;
return 0;
}
3.5 最小生成树
3.5.1 1140. 最短网络
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n;
int g[N][N];
int dis[N];
bool st[N];
int prim()
{
memset(dis,0x3f,sizeof dis);
int res=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j]&&(t==-1||dis[t]>dis[j]))
t=j;
}
if(i&&dis[t]==INF)
return INF;
if(i) res+=dis[t];
st[t]=true;
for(int j=1;j<=n;j++)
dis[j]=min(dis[j],g[t][j]);
}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>g[i][j];
cout<<prim();
return 0;
}
3.5.2 1141. 局域网
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n,m,sum;
int p[N];
struct Edge{
int a,b,w;
bool operator < (const Edge &W)const
{
return w<W.w;
}
}edges[N];
int findP(int x)
{
if(p[x]!=x) p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+m);
for(int i=1;i<=n;i++) p[i]=i;
int res=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res+=w;
}
}
return res;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
edges[i].a=a,edges[i].b=b,edges[i].w=c;
sum+=c;
}
cout<<sum-kruskal()<<endl;
return 0;
}
3.5.3 1142. 繁忙的都市
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=310,M=80010;
int n,m;
int p[N];
struct Edge{
int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n;i++) p[i]=i;
int res=-1;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res=max(res,w);
}
}
return res;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>edges[i].a>>edges[i].b>>edges[i].w;
cout<<n-1<<" "<<kruskal()<<endl;
return 0;
}
3.5.4 1143. 联络员
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2010,M=10010;
int n,m;
int p[N];
struct Edge{
int a,b,w,type;
}edges[M];
bool cmp(Edge a,Edge b)
{
if(a.type!=b.type)
return a.type<b.type;
else
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n;i++) p[i]=i;
int res=0;
for(int i=0;i<m;i++)
{
int type=edges[i].type,a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res+=w;
}
else if(type==1)
{
res+=w;
}
}
return res;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>edges[i].type>>edges[i].a>>edges[i].b>>edges[i].w;
cout<<kruskal();
return 0;
}
3.5.5 1144. 连接格点
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=2000010;
int n,m;
int p[M];
int cnt;
int mp[M];
int dx[2]={0,1},dy[2]={1,0};
struct Edge{
int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+cnt,cmp);
int res=0;
for(int i=0;i<cnt;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res+=w;
}
}
return res;
}
int main()
{
cin>>n>>m;
int x1,y1,x2,y2;
for(int i=1;i<=N*N;i++) p[i]=i;
while(cin>>x1>>y1>>x2>>y2)
{
int a=(x1-1)*n+y1,b=(x2-1)*n+y2;
mp[a]=b;
a=findP(a),b=findP(b);
if(a!=b)
p[a]=b;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=0;k<2;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x<=0||x>n||y<=0||y>m)
continue;
int a=(i-1)*n+j,b=(x-1)*n+y;
if(mp[a]==b)
continue;
edges[cnt].a=a,edges[cnt].b=b;
if(i==x)
edges[cnt].w=2;
else
edges[cnt].w=1;
cnt++;
}
}
}
cout<<kruskal();
return 0;
}
3.6 最小生成树的扩展应用
3.6.1 1146. 新的开始
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=310,M=100010;
int n,m;
int p[N];
int money[N];
struct Edge{
int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n+1;i++) p[i]=i;
int res=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res+=w;
}
}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>money[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int w;
cin>>w;
if(i<j)
{
edges[m].a=i,edges[m].b=j,edges[m].w=w;
m++;
}
}
}
for(int i=1;i<=n;i++)
{
edges[m].a=n+1,edges[m].b=i,edges[m].w=money[i];
m++;
}
cout<<kruskal();
return 0;
}
3.6.2 1145. 北极通讯网络
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=510,M=250010;
int n,m,k;
int p[N];
PII mp[N];
struct Edge{
int a,b;
double w;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
int check()
{
set<int> st;
for(int i=1;i<=n;i++)
{
st.insert(findP(i));
}
return st.size();
}
double kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n;i++) p[i]=i;
double res=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b;
double w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
p[a]=b;
res=w;
}
if(check()<=k)
break;
}
return res;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
mp[i]=make_pair(x,y);
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
double x1=mp[i].first,y1=mp[i].second,x2=mp[j].first,y2=mp[j].second;
double w=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
edges[m].a=i,edges[m].b=j,edges[m].w=w;
m++;
}
}
printf("%.2f",kruskal());
return 0;
}
3.6.3 346. 走廊泼水节
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=6010,M=6010;
int T,n,m;
int p[N],sz[N];
map<PII,int> mp;
struct Edge{
int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
int kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n;i++)
{
p[i]=i;
sz[i]=1;
}
int res=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=findP(a),b=findP(b);
if(a!=b)
{
res+=(sz[a]*sz[b]-1)*(w+1);
sz[b]+=sz[a];
p[a]=b;
}
}
return res;
}
int main()
{
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i<n-1;i++)
{
int a,b,w;
cin>>a>>b>>w;
edges[i].a=a,edges[i].b=b,edges[i].w=w;
}
m=n-1;
cout<<kruskal()<<endl;
}
return 0;
}
3.6.4 1148. 秘密的牛奶运输
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=510,M=10010;
const LL INF=1e18;
int n,m;
int p[N];
int dis1[N][N],dis2[N][N];
int h[N],e[N*2],w[N*2],ne[N*2],idx;
struct Edge{
int a,b,w;
bool type;
}edges[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int findP(int x)
{
if(p[x]!=x) return p[x]=findP(p[x]);
return p[x];
}
void dfs(int u,int fa,int maxd1,int maxd2,int d1[],int d2[])
{
d1[u]=maxd1,d2[u]=maxd2;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(j!=fa)
{
int td1=maxd1,td2=maxd2;
if(w[i]>td1) td2=td1,td1=w[i];
else if(w[i]<td1&&w[i]>td2) td2=w[i];
dfs(j,u,td1,td2,d1,d2);
}
}
}
LL kruskal()
{
sort(edges,edges+m,cmp);
for(int i=1;i<=n;i++) p[i]=i;
LL res=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
int pa=findP(a),pb=findP(b);
if(pa!=pb)
{
p[pa]=pb;
add(a,b,w),add(b,a,w);
edges[i].type=true;
res+=w;
}
}
return res;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>edges[i].a>>edges[i].b>>edges[i].w;
}
LL sum=kruskal();
for(int i=1;i<=n;i++)
dfs(i,-1,-1e9,-1e9,dis1[i],dis2[i]);
LL res=INF;
for(int i=0;i<m;i++)
{
if(!edges[i].type)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
if(w>dis1[a][b])
{
res=min(res,sum+w-dis1[a][b]);
}
else if(w>dis2[a][b])
{
res=min(res,sum+w-dis2[a][b]);
}
}
}
cout<<res;
return 0;
}