老是感觉自己有一种心有余而力不足的感觉,一个简单的Dijkstra都花了我一天的时间去学习,有好多时候都是明明看的懂解释,却没有办法实现,总地有参照才可以写出来,
是不是 因为做题太少,对题解有依赖,都无从得知。写博客也只是在借鉴别人,把自己所做过的题 ,所有的思路都记录下来,在参加比赛之前 有一个复习有一个回顾,也可能是无用功吧,不管是会不会有效吧,做了总比没做强,希望借此改变现状 。
Dijkstra
void dijkstra(int s){//优先级队列的作用:把所有的点分为四种:1用过了的2正在用 的3与正在用有关的点4不符合的。这样 每次会把与正在用的点相关的边放进去,并不断地更新最短路实现遍历所有的边并找出最短路。
int i,j,k,pr=s;
for(i=1;i<=n;i++)d[i]=inf;
priority_queue<qnode> q;
d[pr]=0;
q.push((qnode){pr,0});
path[pr]=1;//记录路径数
while(!q.empty()){
qnode u=q.top();
q.pop();
if(b[u.v])continue;
b[pr=u.v]=1;
for(j=head[pr];j;j=e[j].next){
k=e[j].to;
if(d[pr]+e[j].w==d[k])
path[k]=(path[k]+path[pr])%M;//如果有多条最短路用此来记录看其是否为唯一的,又因为可能爆ll所以取模
else if(d[pr]+e[j].w<d[k]){//第一次的时候因为都是INF所每一个都会被加进que中,所以就是遍历了所有的路,并且只记录了所有的最短路并没有记录其他的。
d[k]=d[pr]+e[j].w;
q.push((qnode){k,d[k]});
path[k]=path[pr];
}
}
}
}
例题 :cf 567E
题意是总统要回家,让你找出最短路,如果现有的最短路必须要用到某一条边,就输出YES。再如果是一定不会走的边如图
A点的那条边就一定不会通过所以就输出NO。剩下的就输出每条边需要减少多少权值才可以成为最短路。
题解:先正者一边dijkstra在反着一遍,这样就可以用 d[0][u]+d[1][v]+W-min+1来算出所需要修的 最小值(0和1表示正反)
并且在过程中记录路径数,若path[0][u]*path[1][v]==path[0][t];判断该路是不是必须通过的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 100005
#define M 5462617
#define inf 0x3f3f3f3f3f3f3f3fll
#define ll long long
#define add(u,v,w) e[++cnt]=(edge){v,head[0][u],w};head[0][u]=cnt;e[++cnt]=(edge){u,head[1][v],w};head[1][v]=cnt
using namespace std;
struct edge{
ll to,next,w;
}e[N<<1];
struct road{
ll u,v,w;
}l[N];
struct qnode{
ll v,c;
bool operator <(const qnode &r)const{
return c>r.c;
}
};
ll n,m,s,t,u,v,w,d[2][N],cnt,head[2][N],path[2][N];
bool b[2][N];
void dijkstra(int f){
int i,j,k,pr=f?t:s;
for(i=1;i<=n;i++)d[f][i]=inf;
priority_queue<qnode> q;
d[f][pr]=0;
q.push((qnode){pr,0});
path[f][pr]=1;
while(!q.empty()){
qnode u=q.top();
q.pop();
if(b[f][u.v])continue;
b[f][pr=u.v]=1;
for(j=head[f][pr];j;j=e[j].next){
k=e[j].to;
if(d[f][pr]+e[j].w==d[f][k])
path[f][k]=(path[f][k]+path[f][pr])%M;
else if(d[f][pr]+e[j].w<d[f][k]){
d[f][k]=d[f][pr]+e[j].w;
q.push((qnode){k,d[f][k]});
path[f][k]=path[f][pr];
}
}
}
}
int main() {
int i,j;
cin>>n>>m>>s>>t;
for(i=1;i<=m;i++){
scanf("%lld%lld%lld",&u,&v,&w);
add(u,v,w);
l[i]=(road){u,v,w};
}
dijkstra(0);
dijkstra(1);
for(i=1;i<=m;i++)
{
u=l[i].u;
v=l[i].v;
w=l[i].w;
if(d[0][u]+d[1][v]+w==d[0][t]){
if(path[0][u]*path[1][v]%M==path[0][t])
puts("YES");
else if(w>1)
puts("CAN 1");
else puts("NO");
}
else if(d[0][u]+d[1][v]+1<d[0][t])
printf("CAN %lld\n",d[0][u]+d[1][v]+w-d[0][t]+1);
else
puts("NO");
}
}