才想到开这个坑。之前的背包和区间 DP 有空可能会补几题。
背包
区间 DP
图论(最短路/最小生成树/拓扑排序)
A CF601A The Two Routes
一定有一种交通工具存在一条路径连接 \(1,n\),于是对另一种交通工具跑最短路即可。
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
int n,m,x,y,i,j,k,dis[405][405],sum;
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
memset(dis,0x3f,sizeof(dis));
for (i=1;i<=m;i++){
cin>>x>>y,dis[x][y]=1,dis[y][x]=1;
sum+=((x==1 && y==n) || (x==n && y==1));
}
if (sum!=0)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (dis[i][j]==1) dis[i][j]=dis[0][0];
else dis[i][j]=1;
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
return cout<<(dis[1][n]==dis[0][0]?-1:dis[1][n]),0;
}
B CF59E Shortest Path
BFS 的同时记录上一个经过的点即可。记录前驱的时候记录边,不是点。
启示:BFS 等算法同样是解决最短路问题的有效手段。
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
int n,m,T,i,x,y,z;
struct Edge{
int to,nex,dis,pre,id;
}e[40005];
int h[3005],cnt;
void add_edge(int x,int y){
e[++cnt].to=y,e[cnt].nex=h[x],e[cnt].id=cnt,h[x]=cnt;
}
struct node{
int pre,now,step,id;
} ;
queue <node> Q;
map <pair<pair<int,int> ,int> ,bool> c;
void go(int x){
if (e[x].pre) go(e[x].pre);
cout<<' '<<e[x].to;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>T;
for (i=1;i<=m;i++)
cin>>x>>y,add_edge(x,y),add_edge(y,x);
for (i=1;i<=T;i++)
cin>>x>>y>>z,c[make_pair(make_pair(x,y),z)]=true;
Q.push(node{0,1,0,0});//pre now step id
while (!Q.empty()){
node x=Q.front();
Q.pop();
if (x.now==n){
cout<<x.step<<'\n'<<1;
return go(x.id),0;
}
for (i=h[x.now]; i; i=e[i].nex){
if (c[make_pair(make_pair(x.pre,x.now),e[i].to)]) continue;
if (e[i].dis) continue;
e[i].dis=x.step+1,e[i].pre=x.id;
Q.push((node){x.now,e[i].to,x.step+1,i});
}
}
return cout<<-1,0;
}
C CF1196F K-th Path
\(k\le400\),从这方面入手,取最短的 \(k\) 条边,至多 \(2k\) 个点做最短路,可以证明答案一定在其中。
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct Edge{int x,y,z;} e[200005];
bool cmp(Edge x,Edge y){return x.z<y.z;}
priority_queue <int,vector<int>,greater<int> > Q;
int n,m,k,i,j,tot,f[805][805],rnk[200005],vis[200005];
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for (i=1;i<=m;i++) cin>>e[i].x>>e[i].y>>e[i].z;
if (m>k) sort (e+1,e+1+m,cmp);
for (i=1;i<=min(m,k);i++) vis[e[i].x]=1,vis[e[i].y]=1;
for (i=1;i<=n;i++)
if (vis[i]) rnk[i]=(++tot);
memset(f,0x3f,sizeof(f));
for (i=1;i<=min(m,k);i++)
f[rnk[e[i].x]][rnk[e[i].y]]=f[rnk[e[i].y]][rnk[e[i].x]]=e[i].z;
for (int _=1;_<=tot;_++)
for (i=1;i<=tot;i++)
for (j=1;j<=tot;j++)
f[i][j]=min(f[i][j],f[i][_]+f[_][j]);
for (i=1;i<=tot;i++)
for (j=i+1;j<=tot;j++)
Q.push(f[i][j]);
for (i=1;i<k;i++) Q.pop();
return cout<<Q.top(),0;
}
D CF1307D Cow and Fields
周六补。