路数有限制(w的倍数)的最短路,【二维dijkstra】 双重限制并输出路径和方法数
2016-03-31 12:07
399 查看
比一般的dijkstra数组多了一维。
小坑,钻了两个小时。头晕。前向星和优先队列写法规范。
#include<bits/stdc++.h>
#define ll long long
using namespace std; //
struct EDGE{
int u,v,w,next;
}edge[500*500*2+5];
int head[500*500+5],pp;
void init(){
pp=0;
memset(head,0,sizeof(head));
}
void add(int u,int v,int w){
edge[++pp]=(EDGE){u,v,w,head[u]};
head[u]=pp;
}
int n,m,a,b,c,d,e;
int x[505];
int vis[505];
int dis[505];
int cost[505];
int path[505];
int times[505];
struct cmp{
bool operator()(const int &t1,const int &t2){
if(dis[t1]!=dis[t2])
return dis[t1]>dis[t2];
return cost[t1]<cost[t2];
}
};
int main(){
cin>>n>>m>>a>>b;
init();
for(int i=0;i<n;++i)
cin>>x[i];
while(m--){
cin>>c>>d>>e;
add(c,d,e);
add(d,c,e);
}
for(int i=0;i<n;++i)
dis[i]=100000000;
priority_queue<int,vector<int>,cmp> q;
q.push(a);
dis[a]=0;
cost[a]=x[a];
times[a]=1;
while(!q.empty()){
int u=q.top();
q.pop();
if(vis[u]==1) continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(vis[v]==1) continue;
if(dis[u]+w<dis[v]) times[v]=times[u];
else if(dis[u]+w==dis[v]) times[v]+=times[u];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
else if(dis[u]+w==dis[v]&&cost[u]+x[v]>cost[v]){
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
}
}
cout<<times[b]<<" "<<cost[b]<<endl;
stack<int> st;
int tmp=b;
while(path[b]!=a){
st.push(path[b]);
b=path[b];
}
cout<<a;
while(!st.empty()){
cout<<" "<<st.top();
st.pop();
}
if(b!=a)
cout<<" "<<tmp;
cout<<endl;
}
#include<iostream> #include<algorithm> #include<map>//ll dx[4]={0,0,-1,1};ll dy[4]={-1,1,0,0}; #include<set>// #include<vector> #include<cmath> #include<stack> #include<string.h> #include<stdlib.h> #include<cstdio> #include<string> #define mod 1000000007 #define ll long long #define inf 10000000000000 #define lowbit(x) (x) & (-x) using namespace std; ll x[102][102]; ll d[102][12]; //记录i点在路数%w=j时的最短路程 int v[102][12]; //判断i点有没有出现过路数%w=j的状态 int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ x[i][j]=inf; } } while(m--){ int a,b; ll c; scanf("%d%d%lld",&a,&b,&c); x[a][b]=min(x[a][b],c); } int st,ed,w; scanf("%d%d%d",&st,&ed,&w); for(int i=0;i<n;++i){ for(int j=0;j<w;++j){ d[i][j]=inf; v[i][j]=0; } } d[st][0]=0; while(1){ //本来这里是for(int i=0;i<n;++i) ll get=inf; ll idx=-1,num=-1; for(int i=0;i<n;++i){ for(int j=0;j<w;++j){ if(v[i][j]==0&&d[i][j]<get){ get=d[i][j]; idx=i; num=j; } } } if(idx==-1||(idx==ed&&num==0)) //当前已经无法拓新或者已经找到了终点是w倍数的情况,直接退出 break; v[idx][num]=1; for(int i=0;i<n;++i){ if(x[idx][i]==inf||v[i][(num+1)%w]==1) continue; d[i][(num+1)%w]=min(d[i][(num+1)%w],d[idx][num]+x[idx][i]); } } if(d[ed][0]==inf) printf("No Answer!\n"); else printf("%lld\n",d[ed][0]); } return 0; }https://www.patest.cn/contests/gplt/L2-001
小坑,钻了两个小时。头晕。前向星和优先队列写法规范。
#include<bits/stdc++.h>
#define ll long long
using namespace std; //
struct EDGE{
int u,v,w,next;
}edge[500*500*2+5];
int head[500*500+5],pp;
void init(){
pp=0;
memset(head,0,sizeof(head));
}
void add(int u,int v,int w){
edge[++pp]=(EDGE){u,v,w,head[u]};
head[u]=pp;
}
int n,m,a,b,c,d,e;
int x[505];
int vis[505];
int dis[505];
int cost[505];
int path[505];
int times[505];
struct cmp{
bool operator()(const int &t1,const int &t2){
if(dis[t1]!=dis[t2])
return dis[t1]>dis[t2];
return cost[t1]<cost[t2];
}
};
int main(){
cin>>n>>m>>a>>b;
init();
for(int i=0;i<n;++i)
cin>>x[i];
while(m--){
cin>>c>>d>>e;
add(c,d,e);
add(d,c,e);
}
for(int i=0;i<n;++i)
dis[i]=100000000;
priority_queue<int,vector<int>,cmp> q;
q.push(a);
dis[a]=0;
cost[a]=x[a];
times[a]=1;
while(!q.empty()){
int u=q.top();
q.pop();
if(vis[u]==1) continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(vis[v]==1) continue;
if(dis[u]+w<dis[v]) times[v]=times[u];
else if(dis[u]+w==dis[v]) times[v]+=times[u];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
else if(dis[u]+w==dis[v]&&cost[u]+x[v]>cost[v]){
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
}
}
cout<<times[b]<<" "<<cost[b]<<endl;
stack<int> st;
int tmp=b;
while(path[b]!=a){
st.push(path[b]);
b=path[b];
}
cout<<a;
while(!st.empty()){
cout<<" "<<st.top();
st.pop();
}
if(b!=a)
cout<<" "<<tmp;
cout<<endl;
}
相关文章推荐
- Web报表工具FineReport二次开发JS之字符串
- hibernate与mybatis异同与比较 (涵盖网上各个版本,清晰明了)
- hibernate延迟加载(get和load的区别)
- Web报表工具FineReport二次开发JS之字符串
- Html+CSS input type=file 文件类型限制属性 accept (HTML 5)
- 在程序中启动另一个程序
- Eclipse安装应知应会
- Android-include获取其子标签并且设置事件
- objective-c常见类型%z
- Java内存模型总结
- GHOST 误操作的恢复方法
- C# Window编程随记——运行时动态对象创建和动态方法调用
- 真机调试没有问题。但是打包IPA包运行就会闪退
- .net 已安装的插件卸载方法
- 0004 plsql的安装
- GNU LIBC源代码学习之strcmp
- Spring框架:Spring容器具体解释
- 【angularJs】--入门实例二
- 为什么 iOS 开发中,xib跟storyboard拖得控件一般为 weak 而不是 strong
- DDL语句--查看表