标签:最短路
双条件最短路
每个路有已搭建和未搭建两种状态 需要把经过的路都建起 为经过的路都拆掉
优先经过最少条路 同样少的路走改动(搭建+拆掉)最小的
最短路跑完后把最短的路上的路径标记一下
bfs输出拆除和搭建 在最短路径上的路 未建的搭建 不在的建好的拆掉
通过此题试了一下spfa的一个小优化还有dijkstra的优先队列优化
不过别看spfa加优化快了点 前两天做了个专门卡这个优化的题……想方设法让他多跑就是。。HDOJ 4889 有兴趣的可以去瞅瞅
此题代码如下:
//spfa 109ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define sz 100000
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge//邻接表建图
{
int v,next,hs;
int in;
}Edge;
bool vis[sz+1];
Edge eg[2*sz+2];
int head[sz+1];
int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];//rep重建路数 dis经过路数 site当前点与前驱点间路下标 用以标记 pre前驱
int alb,n,m,tp;
void Add(int u,int v,int w)
{
eg[tp].v = v;
eg[tp].hs = w;
eg[tp].next = head[u];
eg[tp].in = 0;
head[u] = tp++;
}
void spfa()
{
queue <int> q;
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(rep,INF,sizeof(rep));
int i,u,v,p,ned;
q.push(1);
dis[1] = rep[1] = 0;
pre[1] = vis[1] = 1;
while(!q.empty())
{
u = q.front();
q.pop();
if(u == n) return;
for(i = head[u]; i != -1; i = eg[i].next)
{
ned = eg[i].hs^1;
v = eg[i].v;
if(dis[u]+1 < dis[v] || (dis[u]+1 == dis[v] && rep[u] + ned < rep[v]))
{
site[v] = i;
pre[v] = u;
dis[v] = dis[u]+1;
rep[v] = rep[u] + ned;
if(!vis[v])
{
q.push(v);
vis[v] = 1;
}
}
}
}
}
void Bfs()
{
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(1);
int i,u,v;
vis[1] = 1;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = head[u]; i != -1; i = eg[i].next)
{
if(eg[i].in == -1) continue;
v = eg[i].v;
if(!eg[i].hs && eg[i].in)//路未建且在路径中
{
printf("%d %d 1\n",u,v);
}
else if(eg[i].hs && !eg[i].in)//路已建但不在路径中
{
printf("%d %d 0\n",u,v);
}
eg[i].in = eg[i^1].in = -1;
if(!vis[v])
{
q.push(v);
vis[v] = 1;
}
}
}
puts("");
}
int main()
{
int u,v,w;
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
tp = alb = 0;
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
Add(v,u,w);
if(w) alb++;//累加已建路数
}
spfa();
for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;//标记最短路径上的路
printf("%d\n",rep[n]*2 + alb - dis[n]);//rep+(alb-(dis-rep))
Bfs();
return 0;
}
//spfa+优化93ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define sz 100000
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge
{
int v,next,hs;
int in;
}Edge;
bool vis[sz+1];
Edge eg[2*sz+2];
int head[sz+1];
int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];
int alb,n,m,tp;
void Add(int u,int v,int w)
{
eg[tp].v = v;
eg[tp].hs = w;
eg[tp].next = head[u];
eg[tp].in = 0;
head[u] = tp++;
}
void spfa()
{
deque <int> q;
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(rep,INF,sizeof(rep));
int i,u,v,p,ned;
q.push_front(1);
dis[1] = rep[1] = 0;
pre[1] = vis[1] = 1;
while(!q.empty())
{
u = q.front();
q.pop_front();
if(u == n) return;
for(i = head[u]; i != -1; i = eg[i].next)
{
ned = eg[i].hs^1;
v = eg[i].v;
if(dis[u]+1 < dis[v] || (dis[u]+1 == dis[v] && rep[u] + ned < rep[v]))
{
site[v] = i;
pre[v] = u;
dis[v] = dis[u]+1;
rep[v] = rep[u] + ned;
if(!vis[v])
{
if(!q.empty()) p = q.front();
if(!q.empty() && (dis[v] < dis[p] || (dis[v] == dis[p] && rep[v] < rep[p])) )q.push_front(v);
else q.push_back(v);
vis[v] = 1;
}
}
}
}
}
void Bfs()
{
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(1);
int i,u,v;
vis[1] = 1;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = head[u]; i != -1; i = eg[i].next)
{
if(eg[i].in == -1) continue;
v = eg[i].v;
if(!eg[i].hs && eg[i].in)
{
printf("%d %d 1\n",u,v);
}
else if(eg[i].hs && !eg[i].in)
{
printf("%d %d 0\n",u,v);
}
eg[i].in = eg[i^1].in = -1;
if(!vis[v])
{
q.push(v);
vis[v] = 1;
}
}
}
puts("");
}
int main()
{
int u,v,w;
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
tp = alb = 0;
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
Add(v,u,w);
if(w) alb++;
}
spfa();
for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;
printf("%d\n",rep[n]*2 + alb - dis[n]);
Bfs();
return 0;
}
//dijkstra+优化108ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#define sz 100000
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Edge
{
int v,next,hs;
int in;
}Edge;
bool vis[sz+1];
Edge eg[2*sz+2];
int head[sz+1];
int rep[sz+1],dis[sz+1],site[sz+1],pre[sz+1];
int alb,n,m,tp;
void Add(int u,int v,int w)
{
eg[tp].v = v;
eg[tp].hs = w;
eg[tp].next = head[u];
eg[tp].in = 0;
head[u] = tp++;
}
struct cmp
{
bool operator() (int a,int b)
{
return dis[a] > dis[b] || (dis[a] == dis[b] && rep[a] > rep[b]);
}
};
void Dijkstra()
{
priority_queue <int,vector<int>,cmp> q;
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(rep,INF,sizeof(rep));
dis[1] = rep[1] = 0;
pre[1] = 1;
q.push(1);
int i,v,p,mm,j,ss,ned;
while(1)
{
p = q.top();
q.pop();
if(p == n) return;
vis[p] = 1;
for(j = head[p]; j != -1; j = eg[j].next)
{
v = eg[j].v;
ned = eg[j].hs^1;
if(!vis[v] && (dis[p] + 1 < dis[v] || (dis[p]+1 == dis[v] && rep[p] + ned < rep[v])))
{
dis[v] = dis[p] + 1;
rep[v] = rep[p] +ned;
site[v] = j;
pre[v] = p;
q.push(v);
}
}
}
}
void Bfs()
{
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(1);
int i,u,v;
vis[1] = 1;
while(!q.empty())
{
u = q.front();
q.pop();
for(i = head[u]; i != -1; i = eg[i].next)
{
if(eg[i].in == -1) continue;
v = eg[i].v;
if(!eg[i].hs && eg[i].in)
{
printf("%d %d 1\n",u,v);
}
else if(eg[i].hs && !eg[i].in)
{
printf("%d %d 0\n",u,v);
}
eg[i].in = eg[i^1].in = -1;
if(!vis[v])
{
q.push(v);
vis[v] = 1;
}
}
}
puts("");
}
int main()
{
int u,v,w;
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
tp = alb = 0;
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
Add(u,v,w);
Add(v,u,w);
if(w) alb++;
}
Dijkstra();
for(u = n; u != pre[u]; u = pre[u]) eg[site[u]].in = eg[site[u]^1].in = 1;
printf("%d\n",rep[n]*2 + alb - dis[n]);
Bfs();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:最短路
原文地址:http://blog.csdn.net/challengerrumble/article/details/47721651