因为以前太懒,所以前没发什么博客。今天本人第一天写博客吧,hh
因为本人擅长图论就从图论开始吧。
说到图论,不得不提最短路问题。
简单看看最短路吧hh
dijkstra(优先队列优化)
void dijkstra(int s)
{
memset(d,0x7f,sizeof(d));
memset(v,0,sizeof(v));
d[s]=0;
q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second;
q.pop();
if(v[x]) continue;
v[x]=1;
for(int i=head[x];i;i=next[i])
{
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
q.push(make_pair(-d[y],y));
}
}
}
}
spfa(bfs版)
void spfa()
{
memset(d,0x3f,sizeof(d));
d[u]=1;
visit[u]=1;
q.push(u);
while(q.size())
{
int x=q.front();
q.pop();
visit[x]=0;
for(int i=0;i<b[x].size();i++)
{
int y=b[x][i];
double z=a[x][y];
if(d[y]<d[x]*z)
{
d[y]=d[x]*z;
if(!visit[y]) q.push(y),visit[y]=1;
}
}
visit[x]=1;
}
}
spfa(dfs版,没听说过吧)
void spfa(int x)
{
if(flag) return;
v[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
double z=e[i].dis;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(!v[y]) spfa(y);
else
{
flag=1;
return;
}
}
}
v[x]=0;
}
这里特别提一下,为什么要会深搜的spfa
以下题为例:
洛谷P1768
[link] (https://www.luogu.com.cn/problem/P1768)
题目描述
“那是一条神奇的天路诶~~~,把第一个神犇送上天堂~~~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了。
和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了,旨在难到一帮大脑不够灵活的OIer们(JOHNKRAM真的不是说你……)。
言归正传,小X的梦中,他在西藏开了一家大型旅游公司,现在,他要为西藏的各个景点设计一组铁路线。但是,小X发现,来旅游的游客都很挑剔,他们乘火车在各个景点间游览,景点的趣味当然是不用说啦,关键是路上。试想,若是乘火车一圈转悠,却发现回到了游玩过的某个景点,花了一大堆钱却在路上看不到好的风景,那是有多么的恼火啊。
所以,小X为所有的路径定义了两个值,Vi和Pi,分别表示火车线路的风景趣味度和乘坐一次的价格。现在小X想知道,乘客从任意一个景点开始坐火车走过的一条回路上所有的V之和与P之和的比值的最大值。以便为顾客们推荐一条环绕旅游路线(路线不一定包含所有的景点,但是不可以存在重复的火车路线)。
于是,小X梦醒之后找到了你……
输入格式
第一行两个正整数N,M,表示有N个景点,M条火车路线,火车路线是单向的。
以下M行,每行4个正整数,分别表示一条路线的起点,终点,V值和P值。
注意,两个顶点间可能有多条轨道,但一次只能走其中的一条。
输出格式
一个实数,表示一条回路上最大的比值,保留1位小数。
若没有回路,输出-1。
输入输出样例
输入 #1复制
5 6
1 2 1 1
4 1 6 2
5 4 8 1
2 3 2 2
5 2 4 1
3 5 6 4
输出 #1复制
2.3
说明/提示
对于30%的数据,1≤N≤100,1≤M≤20;
对于60%的数据,1≤N≤3,000,1≤M≤2,000;
对于100%的数据,1≤N≤7,000,1≤M≤20,000,1≤Vi,Pi≤1,000.
保证答案在200以内.
首先,这道题有负环,因此不能用dijkstra。
在最开始的时候,我就交了一个简单的SPFA上去,果不其然,它死了。
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define eps 1e-5
//#define mod 1e9+7
using namespace std;
const int mod=1e9;
const int N=4e4+5;
int n,m;
struct node
{
int ver,next;
double edge1,edge2,dis;
}e[N];
double l,r=200;
int head[N],tot;
double d[N];
int v[N],cnt[N];
bool flag;
void add(int x,int y,double v,double p)
{
e[++tot].ver=y;
e[tot].edge1=v;
e[tot].edge2=p;
e[tot].next=head[x];
head[x]=tot;
}
bool spfa(int s)
{
for(int i=1;i<=n;i++)
{
v[i]=0;
d[i]=1e9;
cnt[i]=0;
}
d[s]=0;
v[s]=1;
queue < int > q;
q.push(s);
while(q.size())
{
int x=q.front();
q.pop();
if(cnt[x]>20) return true;
v[x]=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
double z=e[i].dis;
if(d[y]>d[x]+z)
{
cnt[y]++;
d[y]=d[x]+z;
if(cnt[y]>20) return true;
if(!v[y])
{
v[y]=1;
q.push(y);
}
}
}
}
return false;
}
signed main()
{
// ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
double v,p;
scanf("%d%d%lf%lf",&x,&y,&v,&p);
add(x,y,v,p);
}
while(r-l>=1e-2)
{
double mid=(r+l)/2;
flag=0;
for(int i=1;i<=tot;i++) e[i].dis=e[i].edge2*mid-e[i].edge1;
for(int i=1;i<=n;i++)
{
flag=spfa(1) || spfa(n) || spfa(n >> 1);
if(flag) break;
}
if(flag) l=mid;
else r=mid;
}
if(l==0) cout<<"-1";
else printf("%.1lf",r);
return 0;
}
剪枝+O2:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define eps 1e-5
//#define mod 1e9+7
using namespace std;
const int mod=1e9;
const int N=4e4+5;
int n,m;
struct node
{
int ver,next;
double edge1,edge2,dis;
}e[N];
double l,r=200;
int head[N],tot;
double d[N];
int v[N],cnt[N];
bool flag;
void add(int x,int y,double v,double p)
{
e[++tot].ver=y;
e[tot].edge1=v;
e[tot].edge2=p;
e[tot].next=head[x];
head[x]=tot;
}
bool spfa(int s)
{
for(int i=1;i<=n;i++)
{
v[i]=0;
d[i]=1e9;
cnt[i]=0;
}
d[s]=0;
v[s]=1;
queue < int > q;
q.push(s);
while(q.size())
{
int x=q.front();
q.pop();
if(cnt[x]>20) return true;
v[x]=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
double z=e[i].dis;
if(d[y]>d[x]+z)
{
cnt[y]++;
d[y]=d[x]+z;
if(cnt[y]>20) return true;
if(!v[y])
{
v[y]=1;
q.push(y);
}
}
}
}
return false;
}
signed main()
{
// ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
double v,p;
scanf("%d%d%lf%lf",&x,&y,&v,&p);
add(x,y,v,p);
}
while(r-l>=1e-2)
{
double mid=(r+l)/2;
flag=0;
for(int i=1;i<=tot;i++) e[i].dis=e[i].edge2*mid-e[i].edge1;
flag=spfa(1) || spfa(n) || spfa(n >> 1);
if(flag) l=mid;
else r=mid;
}
if(l==0) cout<<"-1";
else printf("%.1lf",r);
return 0;
}
spfa(dfs):
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define eps 1e-5
//#define mod 1e9+7
using namespace std;
const int mod=1e9;
const int N=4e4+5;
int n,m;
struct node
{
int ver,next;
double edge1,edge2,dis;
}e[N];
double l,r=200;
int head[N],tot;
double d[N];
int v[N],cnt[N];
bool flag;
void add(int x,int y,double v,double p)
{
e[++tot].ver=y;
e[tot].edge1=v;
e[tot].edge2=p;
e[tot].next=head[x];
head[x]=tot;
}
void spfa(int x)
{
if(flag) return;
v[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
double z=e[i].dis;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(!v[y]) spfa(y);
else
{
flag=1;
return;
}
}
}
v[x]=0;
}
signed main()
{
// ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
double v,p;
scanf("%d%d%lf%lf",&x,&y,&v,&p);
add(x,y,v,p);
}
while(r-l>=1e-2)
{
double mid=(r+l)/2;
flag=0;
for(int i=1;i<=tot;i++) e[i].dis=e[i].edge2*mid-e[i].edge1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
v[j]=0;
d[j]=1e9;
}
spfa(i);
if(flag) break;
}
if(flag) l=mid;
else r=mid;
}
if(l==0) cout<<"-1";
else printf("%.1lf",r);
return 0;
}
bellman-ford
void bellman-ford(int s)
{
memset(d,0x3f,sizeof(d));
d[s]=0;
for(int x=1;x<=n;x++)
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
int z=e[i].edge;
d[y]=min(d[y],d[x]+z);
}
}
扩展和题目就先不说了,期待下一期吧。