最近几天写了一些分层图的题目,来总结一下
分层图有一个很重要的性质:上一层不能到达下一层,但下一层能到达上一层
分层图常常结合最短路,所以叫分层图最短路,当然,也结合缩点之类的
[USACO09FEB]改造路Revamping Trails
双倍经验题[JLOI2011]飞行路线
这是一道分层图最短路裸题
考虑\(dp\),\(dis[i][j]\)表示到达第\(i\)个点已经\(j\)次升级后所经过的最短路径
那么就可以愉快的在\(Dijkstra\)里分类讨论一下
\(Code\ Below:\)
#include <bits/stdc++.h>
#define mp make_pair
#define S second
#define F first
using namespace std;
const int maxn=10000+10;
const int maxm=50000+10;
int n,m,k,head[maxn],dis[maxn][21],vis[maxn][21],tot;
struct node{
int to,next,val;
}e[maxm<<1];
inline int read(){
register int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void add(int x,int y,int w){
e[++tot].to=y;
e[tot].val=w;
e[tot].next=head[x];
head[x]=tot;
}
void Dijkstra(){
memset(dis,0x3f3f3f3f,sizeof(dis));
priority_queue<pair<int,pair<int,int> > > pq;
pair<int,int> u;int v;
dis[1][0]=0;pq.push(mp(0,mp(1,0)));
while(!pq.empty()){
u=pq.top().S;pq.pop();
if(vis[u.F][u.S]) continue;
vis[u.F][u.S]=1;
for(int i=head[u.F];i;i=e[i].next){
v=e[i].to;
if(dis[v][u.S]>dis[u.F][u.S]+e[i].val){
dis[v][u.S]=dis[u.F][u.S]+e[i].val;
pq.push(mp(-dis[v][u.S],mp(v,u.S)));
}
if(u.S+1<=k&&dis[v][u.S+1]>dis[u.F][u.S]){
dis[v][u.S+1]=dis[u.F][u.S];
pq.push(mp(-dis[v][u.S+1],mp(v,u.S+1)));
}
}
}
}
int main()
{
n=read(),m=read(),k=read();
int x,y,w;
for(int i=1;i<=m;i++){
x=read(),y=read(),w=read();
add(x,y,w);add(y,x,w);
}
Dijkstra();
printf("%d\n",dis[n][k]);
return 0;
}
[USACO15JAN]草鉴定Grass Cownoisseur
这道题比刚刚那道麻烦一点
首先看到有环,缩点一下,重新建图。把图复制一遍,将第一层的\(to[i]\)向第二层的\(x\)连一条边
\(Code\ Below:\)
#include <bits/stdc++.h>
#include <time.h>
#define inf 99999999
using namespace std;
const int maxn=100000+10;
int n,m,low[maxn],dfn[maxn],vis[maxn<<1],tim;
int head[maxn<<1],to[maxn<<2],nxt[maxn<<2],tot;
int col[maxn],siz[maxn<<1],color;
int x[maxn],y[maxn],dis[maxn<<1];
stack<int> s;
inline int read(){
register int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void add(int x,int y){
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void tarjan(int u)
{
low[u]=dfn[u]=++tim;
vis[u]=1;s.push(u);
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
color++;
while(s.top()!=u){
vis[s.top()]=0;
col[s.top()]=color;
siz[color]++;
s.pop();
}
vis[u]=0;col[u]=color;siz[color]++;s.pop();
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++){
x[i]=read(),y[i]=read();
add(x[i],y[i]);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
memset(head,0,sizeof(head));
memset(to,0,sizeof(to));
memset(nxt,0,sizeof(nxt));
memset(vis,0,sizeof(vis));
tot=0;
for(int i=1;i<=m;i++)
if(col[x[i]]!=col[y[i]]){
add(col[x[i]],col[y[i]]);
add(col[x[i]]+color,col[y[i]]+color);
add(col[y[i]],col[x[i]]+color);
}
for(int i=1;i<=color;i++) siz[i+color]=siz[i];
queue<int> q;
vis[col[1]]=1;
q.push(col[1]);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(dis[v]<dis[u]+siz[u]){
dis[v]=dis[u]+siz[u];
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
printf("%d\n",dis[col[1]+color]);
return 0;
}
原文地址:https://www.cnblogs.com/owencodeisking/p/9610084.html
时间: 2024-11-13 06:08:37